20 #include "RestHandler.h"
25 #include "spdlog/spdlog.h"
27 using web::json::value;
28 using web::http::methods;
30 using web::http::http_request;
31 using web::http::status_codes;
32 using web::http::experimental::listener::http_listener;
33 using web::http::experimental::listener::http_listener_config;
44 http_listener_config server_config;
45 if (url.rfind(
"https", 0) == 0) {
46 server_config.set_ssl_context_callback(
47 [&](boost::asio::ssl::context& ctx) {
48 std::string cert_file =
"/usr/share/obeca/cert.pem";
49 cfg.lookupValue(
"restful_api.cert", cert_file);
51 std::string key_file =
"/usr/share/obeca/key.pem";
52 cfg.lookupValue(
"restful_api.key", key_file);
54 ctx.set_options(boost::asio::ssl::context::default_workarounds);
55 ctx.use_certificate_chain_file(cert_file);
56 ctx.use_private_key_file(key_file, boost::asio::ssl::context::pem);
60 cfg.lookupValue(
"restful_api.api_key.enabled", _require_bearer_token);
61 if (_require_bearer_token) {
62 _api_key =
"106cd60-76c8-4c37-944c-df21aa690c1e";
63 cfg.lookupValue(
"restful_api.api_key.key", _api_key);
66 _listener = std::make_unique<http_listener>(
69 _listener->support(methods::GET, std::bind(&RestHandler::get,
this, std::placeholders::_1));
70 _listener->support(methods::PUT, std::bind(&RestHandler::put,
this, std::placeholders::_1));
72 _listener->open().wait();
77 void RestHandler::get(http_request message) {
78 spdlog::debug(
"Received GET request {}", message.to_string() );
79 auto paths = uri::split_path(uri::decode(message.relative_uri().path()));
80 if (_require_bearer_token &&
81 (message.headers()[
"Authorization"] !=
"Bearer " + _api_key)) {
82 message.reply(status_codes::Unauthorized);
87 message.reply(status_codes::NotFound);
89 if (paths[0] ==
"status") {
90 auto state = value::object();
94 state[
"state"] = value::string(
"searching");
97 state[
"state"] = value::string(
"syncing");
100 state[
"state"] = value::string(
"synchronized");
104 if (_phy.
cell().nof_prb == _phy.
cell().mbsfn_prb) {
105 state[
"nof_prb"] = value(_phy.
cell().nof_prb);
107 state[
"nof_prb"] = value(_phy.
cell().mbsfn_prb);
109 state[
"cell_id"] = value(_phy.
cell().id);
110 state[
"cfo"] = value(_phy.
cfo());
111 state[
"cinr_db"] = value(
cinr_db());
112 state[
"subcarrier_spacing"] = value(_phy.mbsfn_subcarrier_spacing_khz());
113 message.reply(status_codes::OK, state);
114 }
else if (paths[0] ==
"sdr_params") {
115 value sdr = value::object();
117 sdr[
"gain"] = value(_lime.
get_gain());
122 message.reply(status_codes::OK, sdr);
123 }
else if (paths[0] ==
"ce_values") {
124 auto cestream = Concurrency::streams::bytestream::open_istream(
_ce_values);
125 message.reply(status_codes::OK, cestream);
126 }
else if (paths[0] ==
"pdsch_status") {
127 value sdr = value::object();
128 sdr[
"bler"] = value(
static_cast<float>(
_pdsch.errors) /
129 static_cast<float>(
_pdsch.total));
130 sdr[
"ber"] = value(
_pdsch.ber);
131 sdr[
"mcs"] = value(
_pdsch.mcs);
133 message.reply(status_codes::OK, sdr);
134 }
else if (paths[0] ==
"pdsch_data") {
135 auto cestream = Concurrency::streams::bytestream::open_istream(
_pdsch.GetData());
136 message.reply(status_codes::OK, cestream);
137 }
else if (paths[0] ==
"mcch_status") {
138 value sdr = value::object();
139 sdr[
"bler"] = value(
static_cast<float>(
_mcch.errors) /
140 static_cast<float>(
_mcch.total));
141 sdr[
"ber"] = value(
_mcch.ber);
142 sdr[
"mcs"] = value(
_mcch.mcs);
144 message.reply(status_codes::OK, sdr);
145 }
else if (paths[0] ==
"mcch_data") {
146 auto cestream = Concurrency::streams::bytestream::open_istream(
_mcch.GetData());
147 message.reply(status_codes::OK, cestream);
148 }
else if (paths[0] ==
"mch_info") {
149 std::vector<value> mi;
150 auto mch_info = _phy.mch_info();
151 std::for_each(std::begin(mch_info), std::end(mch_info), [&mi](
Phy::mch_info_t const& mch) {
153 m[
"mcs"] = value(mch.mcs);
154 std::vector<value> mti;
155 std::for_each(std::begin(mch.mtchs), std::end(mch.mtchs), [&mti](
Phy::mtch_info_t const& mtch) {
157 mt[
"tmgi"] = value(mtch.tmgi);
158 mt[
"dest"] = value(mtch.dest);
159 mt[
"lcid"] = value(mtch.lcid);
162 m[
"mtchs"] = value::array(mti);
165 message.reply(status_codes::OK, value::array(mi));
166 }
else if (paths[0] ==
"mch_status") {
167 int idx = std::stoi(paths[1]);
168 value sdr = value::object();
169 sdr[
"bler"] = value(
static_cast<float>(
_mch[idx].errors) /
170 static_cast<float>(
_mch[idx].total));
171 sdr[
"ber"] = value(
_mch[idx].ber);
172 sdr[
"mcs"] = value(
_mch[idx].mcs);
173 sdr[
"present"] = value(
_mch[idx].present);
174 message.reply(status_codes::OK, sdr);
175 }
else if (paths[0] ==
"mch_data") {
176 int idx = std::stoi(paths[1]);
177 auto cestream = Concurrency::streams::bytestream::open_istream(
_mch[idx].GetData());
178 message.reply(status_codes::OK, cestream);
179 }
else if (paths[0] ==
"log") {
180 std::string logfile =
"/var/log/syslog";
182 Concurrency::streams::file_stream<uint8_t>::open_istream(logfile).then(
183 [message](
const Concurrency::streams::basic_istream<unsigned char>&
185 message.reply(status_codes::OK, file_stream,
"text/plain");
191 void RestHandler::put(http_request message) {
192 spdlog::debug(
"Received PUT request {}", message.to_string() );
194 if (_require_bearer_token &&
195 (message.headers()[
"Authorization"] !=
"Bearer " + _api_key)) {
196 message.reply(status_codes::Unauthorized);
200 auto paths = uri::split_path(uri::decode(message.relative_uri().path()));
202 message.reply(status_codes::NotFound);
204 if (paths[0] ==
"sdr_params") {
207 const auto & jval = message.extract_json().get();
210 jval.at(
"antenna").as_string(),
211 jval.at(
"frequency").as_integer(),
212 jval.at(
"gain").as_double(),
213 jval.at(
"sample_rate").as_integer(),
214 jval.at(
"filter_bw").as_integer());
216 message.reply(status_codes::OK, answer);
221 void RestHandler::add_cinr_value(
float cinr) {
222 if (_cinr_db.size() > CINR_RAVG_CNT) {
223 _cinr_db.erase(_cinr_db.begin());
225 _cinr_db.push_back(cinr);