10 #include <unordered_map>
13 #include <boost/format.hpp>
14 #include <boost/program_options.hpp>
16 #include <mal/Cii.hpp>
17 #include <mal/Mal.hpp>
18 #include <mal/rr/qos/ConnectionTime.hpp>
19 #include <mal/rr/qos/ReplyTime.hpp>
20 #include <mal/utility/LoadMal.hpp>
21 #include <rad/logger.hpp>
35 template <
class TopicType>
37 std::unique_ptr<elt::mal::ps::Subscriber<TopicType>>
subscriber;
41 template <
class TopicType,
class Func>
43 auto subscriber = elt::mal::CiiFactory::getInstance().getSubscriber<TopicType>(
44 elt::mal::Uri(uri), elt::mal::ps::qos::QoS::DEFAULT, elt::mal::Mal::Properties());
46 subscriber->subscribeAsync(elt::mal::ps::DataEventFilter<TopicType>::all(), func);
47 return {std::move(subscriber), std::move(subscription)};
50 int main(
int argc,
char** argv) {
51 namespace po = boost::program_options;
54 log4cplus::initialize();
57 log4cplus::BasicConfigurator(log4cplus::Logger::getDefaultHierarchy(),
true).configure();
58 RAD_LOG_TO_CONSOLE(
true);
59 RAD_LOG_SETLEVEL(
"TRACE");
64 const std::string base_synopsis(
"ocmServerCtl [--status]");
66 std::vector<std::string> subargs;
70 std::unordered_map<std::string, std::unique_ptr<Requestor>> requestors;
72 std::make_pair(
"std.getstatus",
73 std::make_unique<
SimpleRequestor<decltype(&stdif::StdCmds::GetStatus)>>(
74 &stdif::StdCmds::GetStatus, args)));
76 std::make_pair(
"std.getstate",
78 &stdif::StdCmds::GetState, args)));
80 std::make_pair(
"std.getversion",
81 std::make_unique<
SimpleRequestor<decltype(&stdif::StdCmds::GetVersion)>>(
82 &stdif::StdCmds::GetVersion, args)));
84 std::make_pair(
"std.setloglevel", std::make_unique<SetLogLevelRequestor>(args)));
86 std::make_pair(
"std.init",
88 &stdif::StdCmds::Init, args)));
90 std::make_pair(
"std.enable",
92 &stdif::StdCmds::Enable, args)));
94 std::make_pair(
"std.disable",
96 &stdif::StdCmds::Disable, args)));
98 std::make_pair(
"std.exit",
100 &stdif::StdCmds::Exit, args)));
103 std::make_pair(
"daq.stop",
105 &ocmif::OcmDaq::StopDaq, args)));
107 std::make_pair(
"daq.forcestop",
109 &ocmif::OcmDaq::ForceStopDaq, args)));
111 std::make_pair(
"daq.abort",
113 &ocmif::OcmDaq::AbortDaq, args)));
114 requestors.emplace(std::make_pair(
117 &ocmif::OcmDaq::ForceAbortDaq, args)));
120 std::make_pair(
"daq.getstatus",
122 &ocmif::OcmDaq::GetStatus, args)));
124 std::make_pair(
"daq.getactivelist",
125 std::make_unique<
NoArgRequestor<decltype(&ocmif::OcmDaq::GetActiveList)>>(
126 &ocmif::OcmDaq::GetActiveList, args)));
128 requestors.emplace(std::make_pair(
"daq.start", std::make_unique<StartDaqRequestor>(args)));
130 std::make_pair(
"daq.updatekeywords", std::make_unique<UpdateKeywordsRequestor>(args)));
132 std::make_pair(
"daq.awaitstate", std::make_unique<AwaitStateRequestor>(args)));
134 po::options_description
generic(
"Options");
136 generic.add_options()
138 "produce help message (also use this option for each command to get relevant help)")(
139 "version",
"print version string")
141 po::value<std::string>(&args.
req_addr),
142 "request endpoint without service stem. e.g. zpb://127.0.0.1:4020, defaults to env. "
145 po::value<std::string>(&args.
pub_addr),
146 "publish endpoint, defaults to env $OCM_PUBLISH_EP")
147 (
"json",
"output in JSON format")
148 (
"status",
"subscribe to server topics (requires --pep or $OCM_PUBLISH_EP to be set)")
149 (
"timeout,t", po::value<unsigned>(&args.
timeout)->default_value(10),
"timeout in seconds")
153 po::positional_options_description commands;
154 commands.add(
"command", 1).add(
"subargs", -1);
156 po::options_description hidden(
"");
157 hidden.add_options()(
"command",
"")(
158 "subargs", po::value<std::vector<std::string>>(&subargs),
"");
160 po::options_description all(
"");
161 all.add(
generic).add(hidden);
163 po::options_description visible(
165 "ocmServerCtl --help\n"
166 " show main help\n\n"
167 "ocmServerCtl [args] <command> [<command args>]\n"
168 " send command with arguments\n\n"
169 "ocmServerCtl --status [<command> [<command args>]]\n"
170 " subscribe to topics during execution of command\n"
171 " if command is omitted topics are subscribed to indefinitely \n"
172 " (use ctrl-c to cancel)\n\n"
173 "List of supported commands and their arguments");
174 visible.add(
generic);
176 po::variables_map vm;
178 auto parsed = po::command_line_parser(argc, argv)
180 .positional(commands)
181 .allow_unregistered()
183 po::store(parsed, vm);
186 if (vm.count(
"version")) {
187 std::cerr <<
"ocmServerCtl " << VERSION
197 if (vm.count(
"help") && vm.count(
"command") == 0) {
199 for (
auto const& req : requestors) {
203 if (req.second->Synopsis().empty()) {
204 descr = (boost::format(
"%s %s") % base_synopsis % req.first).str();
206 descr = (boost::format(
"%s %s %s") % base_synopsis % req.first %
207 req.second->Synopsis())
210 po::options_description* opt =
new po::options_description(descr);
211 req.second->AddOptions(*opt);
214 std::cerr << visible << std::endl;
218 if (!vm.count(
"rep") && vm.count(
"command")) {
219 auto ep = getenv(
"OCM_REQUEST_EP");
221 std::cerr <<
"Request endpoint (--rep or $OCM_REQUEST_EP) not provided\n";
226 if (!vm.count(
"pep") && vm.count(
"status")) {
227 auto ep = getenv(
"OCM_PUBLISH_EP");
229 std::cerr <<
"Request endpoint (--pep or $OCM_PUBLISH_EP) not provided\n";
238 if (vm.count(
"command") != 1 && vm.count(
"status") == 0) {
239 std::cerr <<
"No command supplied\n";
242 if (vm.count(
"json")) {
247 auto mal = elt::mal::loadMal(
"zpb", {});
248 args.
mal = mal.get();
249 elt::mal::CiiFactory::getInstance().registerMal(
"zpb", mal);
251 std::optional<Subscription<stdif::StatusTopic>> std_status;
252 std::optional<Subscription<ocmif::DaqStatus>> daq_status;
254 if (vm.count(
"status")) {
258 std_status.emplace(MakeSubcription<stdif::StatusTopic>(
260 [](
auto& sub,
auto const& event) {
261 auto const& sample = event.getData();
262 std::cerr <<
"status: " << sample->getStatus() << std::endl;
264 daq_status.emplace(MakeSubcription<ocmif::DaqStatus>(
265 Uri(args.
pub_addr +
"daq/status"), [](
auto& sub,
auto const& event) {
266 auto const& sample = event.getData();
267 std::cerr <<
"daq: id=" << sample->getId()
268 <<
", state=" << ocmif::ToString(sample->getState())
269 <<
", substate=" << ocmif::ToString(sample->getSubState())
270 <<
", error=" << (sample->getError() ?
"true" :
"false")
276 std::vector<std::string> cmd_args =
277 po::collect_unrecognized(parsed.options, po::include_positional);
278 if (cmd_args.empty()) {
279 if (vm.count(
"status")) {
280 std::cerr <<
"no command provided -> will subscribe indefinitely\n";
282 std::this_thread::sleep_for(std::chrono::milliseconds(100));
291 auto command = vm[
"command"].as<std::string>();
293 auto std_cmds = elt::mal::CiiFactory::getInstance().getClient<stdif::StdCmdsSync>(
295 {std::make_shared<elt::mal::rr::qos::ReplyTime>(std::chrono::seconds(args.
timeout))},
297 auto daq_cmds = elt::mal::CiiFactory::getInstance().getClient<::ocmif::OcmDaqSync>(
299 {std::make_shared<elt::mal::rr::qos::ReplyTime>(std::chrono::seconds(args.
timeout))},
303 auto req_it = requestors.find(command);
304 if (req_it != requestors.end()) {
305 auto descr = (boost::format(
"%s %s %s\n"
306 "Supported arguments <args>") %
307 base_synopsis % req_it->first % req_it->second->Synopsis())
309 po::options_description opt(descr);
310 opt.add_options()(
"command",
"");
311 req_it->second->AddOptions(opt);
313 if (vm.count(
"help")) {
314 std::cerr << opt << std::endl;
318 auto parsed_subargs = po::command_line_parser(cmd_args).options(opt).run();
319 po::store(parsed_subargs, vm);
322 assert(req_it->second);
323 std::vector<std::string> remaining_args =
324 po::collect_unrecognized(parsed_subargs.options, po::include_positional);
326 req_it->second->Handle(*std_cmds, *daq_cmds, vm, remaining_args);
327 std::cerr <<
"Done\n";
330 std::cerr <<
"error: Unknown command: '" << command <<
"'\n";
333 }
catch (ocmif::DaqException
const& e) {
334 std::cerr <<
"DaqException: id: '" << e.getId() <<
"', message: " << e.getMessage()
337 }
catch (po::error
const& e) {
338 std::cerr <<
"error: " << e.what() << std::endl;
340 }
catch (std::exception
const& e) {
341 std::cerr <<
"error: " << e.what() << std::endl;
344 std::cerr <<
"unknown error" << std::endl;