aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/RemoteControl.cpp94
-rw-r--r--lib/RemoteControl.h14
2 files changed, 99 insertions, 9 deletions
diff --git a/lib/RemoteControl.cpp b/lib/RemoteControl.cpp
index 30dcb60..6e9af20 100644
--- a/lib/RemoteControl.cpp
+++ b/lib/RemoteControl.cpp
@@ -25,6 +25,8 @@
#include <list>
#include <string>
#include <iostream>
+#include <sstream>
+#include <iomanip>
#include <string>
#include <algorithm>
@@ -102,6 +104,74 @@ std::list< std::vector<std::string> > RemoteControllers::get_param_list_values(c
return allparams;
}
+
+static std::string escape_json(const std::string &s) {
+ std::ostringstream o;
+ for (auto c = s.cbegin(); c != s.cend(); c++) {
+ switch (*c) {
+ case '"': o << "\\\""; break;
+ case '\\': o << "\\\\"; break;
+ case '\b': o << "\\b"; break;
+ case '\f': o << "\\f"; break;
+ case '\n': o << "\\n"; break;
+ case '\r': o << "\\r"; break;
+ case '\t': o << "\\t"; break;
+ default:
+ if ('\x00' <= *c && *c <= '\x1f') {
+ o << "\\u"
+ << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(*c);
+ } else {
+ o << *c;
+ }
+ }
+ }
+ return o.str();
+}
+
+std::string RemoteControllers::get_params_json(const std::string& name) {
+ RemoteControllable* controllable = get_controllable_(name);
+ const auto& values = controllable->get_all_values();
+
+ std::ostringstream ss;
+ ss << "{ ";
+ size_t ix = 0;
+ for (const auto& element : values) {
+ if (ix > 0) {
+ ss << ",";
+ }
+
+ ss << "\"" << escape_json(element.first) << "\": ";
+
+ const auto& value = element.second;
+ if (std::holds_alternative<string>(value)) {
+ ss << "\"" << escape_json(std::get<string>(value)) << "\"";
+ }
+ else if (std::holds_alternative<double>(value)) {
+ ss << std::defaultfloat << std::get<double>(value);
+ }
+ else if (std::holds_alternative<ssize_t>(value)) {
+ ss << std::get<ssize_t>(value);
+ }
+ else if (std::holds_alternative<size_t>(value)) {
+ ss << std::get<size_t>(value);
+ }
+ else if (std::holds_alternative<bool>(value)) {
+ ss << (std::get<bool>(value) ? "true" : "false");
+ }
+ else if (std::holds_alternative<std::nullopt_t>(value)) {
+ ss << "null";
+ }
+ else {
+ throw std::logic_error("variant alternative not handled");
+ }
+
+ ix++;
+ }
+ ss << " }";
+
+ return ss.str();
+}
+
std::string RemoteControllers::get_param(const std::string& name, const std::string& param) {
RemoteControllable* controllable = get_controllable_(name);
return controllable->get_parameter(param);
@@ -427,10 +497,15 @@ void RemoteControllerZmq::recv_all(zmq::socket_t& pSocket, std::vector<std::stri
bool more = true;
do {
zmq::message_t msg;
- pSocket.recv(msg);
- std::string incoming((char*)msg.data(), msg.size());
- message.push_back(incoming);
- more = msg.more();
+ const auto zresult = pSocket.recv(msg);
+ if (zresult) {
+ std::string incoming((char*)msg.data(), msg.size());
+ message.push_back(incoming);
+ more = msg.more();
+ }
+ else {
+ more = false;
+ }
} while (more);
}
@@ -532,6 +607,15 @@ void RemoteControllerZmq::process()
send_fail_reply(repSocket, err.what());
}
}
+ else if (msg.size() == 2 && command == "showjson") {
+ std::string module((char*) msg[1].data(), msg[1].size());
+ std::string json = rcs.get_params_json(module);
+
+ zmq::message_t zmsg(json.size());
+ memcpy(zmsg.data(), json.data(), json.size());
+
+ repSocket.send(zmsg, zmq::send_flags::none);
+ }
else if (msg.size() == 3 && command == "get") {
std::string module((char*) msg[1].data(), msg[1].size());
std::string parameter((char*) msg[2].data(), msg[2].size());
@@ -561,7 +645,7 @@ void RemoteControllerZmq::process()
}
else {
send_fail_reply(repSocket,
- "Unsupported command. commands: list, show, get, set");
+ "Unsupported command. commands: list, show, get, set, showjson");
}
}
}
diff --git a/lib/RemoteControl.h b/lib/RemoteControl.h
index 2358b3a..4bc3b68 100644
--- a/lib/RemoteControl.h
+++ b/lib/RemoteControl.h
@@ -3,7 +3,7 @@
Her Majesty the Queen in Right of Canada (Communications Research
Center Canada)
- Copyright (C) 2019
+ Copyright (C) 2023
Matthias P. Braendli, matthias.braendli@mpb.li
http://www.opendigitalradio.org
@@ -36,6 +36,8 @@
#endif
#include <list>
+#include <unordered_map>
+#include <variant>
#include <map>
#include <memory>
#include <string>
@@ -113,13 +115,16 @@ class RemoteControllable {
}
/* Base function to set parameters. */
- virtual void set_parameter(
- const std::string& parameter,
- const std::string& value) = 0;
+ virtual void set_parameter(const std::string& parameter, const std::string& value) = 0;
/* Getting a parameter always returns a string. */
virtual const std::string get_parameter(const std::string& parameter) const = 0;
+ using value_t = std::variant<std::string, double, size_t, ssize_t, bool, std::nullopt_t>;
+ using map_t = std::unordered_map<std::string, value_t>;
+
+ virtual const map_t get_all_values() const = 0;
+
protected:
std::string m_rc_name;
std::list< std::vector<std::string> > m_parameters;
@@ -135,6 +140,7 @@ class RemoteControllers {
void check_faults();
std::list< std::vector<std::string> > get_param_list_values(const std::string& name);
std::string get_param(const std::string& name, const std::string& param);
+ std::string get_params_json(const std::string& name);
void set_param(
const std::string& name,