5G-MAG Reference Tools - MBMS Modem
Classes | Public Types | Public Member Functions | Public Attributes | Private Member Functions | Private Attributes | List of all members
RestHandler Class Reference

The RESTful API handler. More...

#include <RestHandler.h>

Collaboration diagram for RestHandler:
Collaboration graph

Classes

class  ChannelInfo
 RX Info pertaining to an SCH (MCCH/MCH or PDSCH) More...
 

Public Types

typedef std::function< void(const std::string &antenna, unsigned fcen, double gain, unsigned sample_rate, unsigned bandwidth)> set_params_t
 Definition of the callback for setting new reception parameters. More...
 

Public Member Functions

 RestHandler (const libconfig::Config &cfg, const std::string &url, state_t &state, SdrReader &sdr, Phy &phy, set_params_t set_params)
 Default constructor. More...
 
virtual ~RestHandler ()
 Default destructor. More...
 
float cinr_db ()
 Current CINR value. More...
 
void add_cinr_value (float cinr)
 

Public Attributes

std::vector< uint8_t > _ce_values = {}
 Time domain subcarrier CE values. More...
 
ChannelInfo _pdsch
 RX info for PDSCH. More...
 
ChannelInfo _mcch
 RX info for MCCH. More...
 
std::map< uint32_t, ChannelInfo_mch
 RX info for MCHs. More...
 

Private Member Functions

void get (web::http::http_request message)
 
void put (web::http::http_request message)
 

Private Attributes

std::vector< float > _cinr_db
 
const libconfig::Config & _cfg
 
std::unique_ptr< web::http::experimental::listener::http_listener > _listener
 
state_t_state
 
SdrReader_sdr
 
Phy_phy
 
set_params_t _set_params
 
bool _require_bearer_token = false
 
std::string _api_key
 

Detailed Description

The RESTful API handler.

Supports GET and PUT verbs for SDR parameters, and GET for reception info

Definition at line 44 of file RestHandler.h.

Member Typedef Documentation

◆ set_params_t

typedef std::function<void(const std::string& antenna, unsigned fcen, double gain, unsigned sample_rate, unsigned bandwidth)> RestHandler::set_params_t

Definition of the callback for setting new reception parameters.

Definition at line 49 of file RestHandler.h.

Constructor & Destructor Documentation

◆ RestHandler()

RestHandler::RestHandler ( const libconfig::Config &  cfg,
const std::string &  url,
state_t state,
SdrReader sdr,
Phy phy,
set_params_t  set_params 
)

Default constructor.

Parameters
cfgConfig singleton reference
urlURL to open the server on
stateReference to the main loop sate
sdrReference to the SDR reader
set_paramsSet parameters callback

Definition at line 35 of file RestHandler.cpp.

38  : _cfg(cfg),
39  _state(state),
40  _sdr(sdr),
41  _phy(phy),
42  _set_params(std::move(set_params)) {
43 
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/5gmag-rt/cert.pem";
49  cfg.lookupValue("modem.restful_api.cert", cert_file);
50 
51  std::string key_file = "/usr/share/5gmag-rt/key.pem";
52  cfg.lookupValue("modem.restful_api.key", key_file);
53 
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);
57  });
58  }
59 
60  cfg.lookupValue("modem.restful_api.api_key.enabled", _require_bearer_token);
62  _api_key = "106cd60-76c8-4c37-944c-df21aa690c1e";
63  cfg.lookupValue("modem.restful_api.api_key.key", _api_key);
64  }
65 
66  _listener = std::make_unique<http_listener>(
67  url, server_config);
68 
69  _listener->support(methods::GET, std::bind(&RestHandler::get, this, std::placeholders::_1)); // NOLINT
70  _listener->support(methods::PUT, std::bind(&RestHandler::put, this, std::placeholders::_1)); // NOLINT
71 
72  _listener->open().wait();
73 }
SdrReader & _sdr
Definition: RestHandler.h:126
std::unique_ptr< web::http::experimental::listener::http_listener > _listener
Definition: RestHandler.h:123
void put(web::http::http_request message)
std::string _api_key
Definition: RestHandler.h:132
const libconfig::Config & _cfg
Definition: RestHandler.h:121
void get(web::http::http_request message)
Definition: RestHandler.cpp:77
state_t & _state
Definition: RestHandler.h:125
bool _require_bearer_token
Definition: RestHandler.h:131
set_params_t _set_params
Definition: RestHandler.h:129
static Config cfg
Global configuration object.
Definition: main.cpp:165
void set_params(const std::string &ant, unsigned fc, double g, unsigned sr, unsigned bw)
Set new SDR parameters and initialize resynchronisation.
Definition: main.cpp:198

◆ ~RestHandler()

RestHandler::~RestHandler ( )
virtualdefault

Default destructor.

Member Function Documentation

◆ add_cinr_value()

void RestHandler::add_cinr_value ( float  cinr)

Definition at line 234 of file RestHandler.cpp.

234  {
235  if (_cinr_db.size() > CINR_RAVG_CNT) {
236  _cinr_db.erase(_cinr_db.begin());
237  }
238  _cinr_db.push_back(cinr);
239 }
const int CINR_RAVG_CNT
Definition: RestHandler.h:38
std::vector< float > _cinr_db
Definition: RestHandler.h:117

◆ cinr_db()

float RestHandler::cinr_db ( )
inline

Current CINR value.

Definition at line 113 of file RestHandler.h.

113 { return _cinr_db.size() ? (std::accumulate(_cinr_db.begin(), _cinr_db.end(), 0) / (_cinr_db.size() * 1.0)) : 0.0; };

◆ get()

void RestHandler::get ( web::http::http_request  message)
private

Definition at line 77 of file RestHandler.cpp.

77  {
78  spdlog::debug("Received GET request {}", message.to_string() );
79  auto paths = uri::split_path(uri::decode(message.relative_uri().path()));
81  (message.headers()["Authorization"] != "Bearer " + _api_key)) {
82  message.reply(status_codes::Unauthorized);
83  return;
84  }
85 
86  if (paths.empty()) {
87  message.reply(status_codes::NotFound);
88  } else {
89  if (paths[0] == "status") {
90  auto state = value::object();
91 
92  switch (_state) {
93  case searching:
94  state["state"] = value::string("searching");
95  break;
96  case syncing:
97  state["state"] = value::string("syncing");
98  break;
99  case processing:
100  state["state"] = value::string("synchronized");
101  break;
102  }
103 
104  if (_phy.cell().nof_prb == _phy.cell().mbsfn_prb) {
105  state["nof_prb"] = value(_phy.cell().nof_prb);
106  } else {
107  state["nof_prb"] = value(_phy.cell().mbsfn_prb);
108  }
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();
116  sdr["frequency"] = value(_sdr.get_frequency());
117  sdr["gain"] = value(_sdr.get_gain());
118  sdr["min_gain"] = value(_sdr.min_gain());
119  sdr["max_gain"] = value(_sdr.max_gain());
120  sdr["filter_bw"] = value(_sdr.get_filter_bw());
121  sdr["antenna"] = value(_sdr.get_antenna());
122  sdr["sample_rate"] = value(_sdr.get_sample_rate());
123  sdr["buffer_level"] = value(_sdr.get_buffer_level());
124  message.reply(status_codes::OK, sdr);
125  } else if (paths[0] == "ce_values") {
126  auto cestream = Concurrency::streams::bytestream::open_istream(_ce_values);
127  message.reply(status_codes::OK, cestream);
128  } else if (paths[0] == "pdsch_status") {
129  value sdr = value::object();
130  sdr["bler"] = value(static_cast<float>(_pdsch.errors) /
131  static_cast<float>(_pdsch.total));
132  sdr["ber"] = value(_pdsch.ber);
133  sdr["mcs"] = value(_pdsch.mcs);
134  sdr["present"] = 1;
135  message.reply(status_codes::OK, sdr);
136  } else if (paths[0] == "pdsch_data") {
137  auto cestream = Concurrency::streams::bytestream::open_istream(_pdsch.GetData());
138  message.reply(status_codes::OK, cestream);
139  } else if (paths[0] == "mcch_status") {
140  value sdr = value::object();
141  sdr["bler"] = value(static_cast<float>(_mcch.errors) /
142  static_cast<float>(_mcch.total));
143  sdr["ber"] = value(_mcch.ber);
144  sdr["mcs"] = value(_mcch.mcs);
145  sdr["present"] = 1;
146  message.reply(status_codes::OK, sdr);
147  } else if (paths[0] == "mcch_data") {
148  auto cestream = Concurrency::streams::bytestream::open_istream(_mcch.GetData());
149  message.reply(status_codes::OK, cestream);
150  } else if (paths[0] == "mch_info") {
151  std::vector<value> mi;
152  auto mch_info = _phy.mch_info();
153  std::for_each(std::begin(mch_info), std::end(mch_info), [&mi](Phy::mch_info_t const& mch) {
154  value m;
155  m["mcs"] = value(mch.mcs);
156  std::vector<value> mti;
157  std::for_each(std::begin(mch.mtchs), std::end(mch.mtchs), [&mti](Phy::mtch_info_t const& mtch) {
158  value mt;
159  mt["tmgi"] = value(mtch.tmgi);
160  mt["dest"] = value(mtch.dest);
161  mt["lcid"] = value(mtch.lcid);
162  mti.push_back(mt);
163  });
164  m["mtchs"] = value::array(mti);
165  mi.push_back(m);
166  });
167  message.reply(status_codes::OK, value::array(mi));
168  } else if (paths[0] == "mch_status") {
169  int idx = std::stoi(paths[1]);
170  value sdr = value::object();
171  sdr["bler"] = value(static_cast<float>(_mch[idx].errors) /
172  static_cast<float>(_mch[idx].total));
173  sdr["ber"] = value(_mch[idx].ber);
174  sdr["mcs"] = value(_mch[idx].mcs);
175  sdr["present"] = value(_mch[idx].present);
176  message.reply(status_codes::OK, sdr);
177  } else if (paths[0] == "mch_data") {
178  int idx = std::stoi(paths[1]);
179  auto cestream = Concurrency::streams::bytestream::open_istream(_mch[idx].GetData());
180  message.reply(status_codes::OK, cestream);
181  } else if (paths[0] == "log") {
182  std::string logfile = "/var/log/syslog";
183 
184  Concurrency::streams::file_stream<uint8_t>::open_istream(logfile).then(
185  [message](const Concurrency::streams::basic_istream<unsigned char>&
186  file_stream) {
187  message.reply(status_codes::OK, file_stream, "text/plain");
188  });
189  }
190  }
191 }
@ syncing
Definition: RestHandler.h:39
@ searching
Definition: RestHandler.h:39
@ processing
Definition: RestHandler.h:39
const std::vector< mch_info_t > & mch_info()
Definition: Phy.h:175
srsran_cell_t cell()
Get the current cell (with params adjusted for MBSFN)
Definition: Phy.h:91
float mbsfn_subcarrier_spacing_khz()
Definition: Phy.h:197
float cfo()
Get the current CFO value.
Definition: Phy.h:108
std::vector< uint8_t > GetData()
Definition: RestHandler.h:76
float cinr_db()
Current CINR value.
Definition: RestHandler.h:113
std::vector< uint8_t > _ce_values
Time domain subcarrier CE values.
Definition: RestHandler.h:93
ChannelInfo _mcch
RX info for MCCH.
Definition: RestHandler.h:103
std::map< uint32_t, ChannelInfo > _mch
RX info for MCHs.
Definition: RestHandler.h:108
ChannelInfo _pdsch
RX info for PDSCH.
Definition: RestHandler.h:98
double get_frequency()
Get current center frequency.
Definition: SdrReader.h:100
double get_buffer_level()
Get current ringbuffer level (0 = empty .
Definition: SdrReader.cpp:369
unsigned get_filter_bw()
Get current filter bandwidth.
Definition: SdrReader.h:105
std::string get_antenna()
Get current antenna port.
Definition: SdrReader.h:120
double max_gain()
Definition: SdrReader.h:129
double min_gain()
Definition: SdrReader.h:127
double get_gain()
Get current gain.
Definition: SdrReader.h:110
double get_sample_rate()
Get current sample rate.
Definition: SdrReader.h:95
std::vector< mtch_info_t > mtchs
Definition: Phy.h:172

◆ put()

void RestHandler::put ( web::http::http_request  message)
private

Definition at line 193 of file RestHandler.cpp.

193  {
194  spdlog::debug("Received PUT request {}", message.to_string() );
195 
196  if (_require_bearer_token &&
197  (message.headers()["Authorization"] != "Bearer " + _api_key)) {
198  message.reply(status_codes::Unauthorized);
199  return;
200  }
201 
202  auto paths = uri::split_path(uri::decode(message.relative_uri().path()));
203  if (paths.empty()) {
204  message.reply(status_codes::NotFound);
205  } else {
206  if (paths[0] == "sdr_params") {
207  value answer;
208 
209  auto f = _sdr.get_frequency();
210  auto g = _sdr.get_gain();
211  auto bw = _sdr.get_filter_bw();
212  auto a = _sdr.get_antenna();
213  auto sr = _sdr.get_sample_rate();
214 
215  const auto & jval = message.extract_json().get();
216  spdlog::debug("Received JSON: {}", jval.serialize());
217 
218  if (jval.has_field("antenna")) {
219  a = jval.at("antenna").as_string();
220  }
221  if (jval.has_field("frequency")) {
222  f = jval.at("frequency").as_integer();
223  }
224  if (jval.has_field("gain")) {
225  g = jval.at("gain").as_double();
226  }
227  _set_params( a, f, g, sr, bw);
228 
229  message.reply(status_codes::OK, answer);
230  }
231  }
232 }

Member Data Documentation

◆ _api_key

std::string RestHandler::_api_key
private

Definition at line 132 of file RestHandler.h.

◆ _ce_values

std::vector<uint8_t> RestHandler::_ce_values = {}

Time domain subcarrier CE values.

Definition at line 93 of file RestHandler.h.

◆ _cfg

const libconfig::Config& RestHandler::_cfg
private

Definition at line 121 of file RestHandler.h.

◆ _cinr_db

std::vector<float> RestHandler::_cinr_db
private

Definition at line 117 of file RestHandler.h.

◆ _listener

std::unique_ptr<web::http::experimental::listener::http_listener> RestHandler::_listener
private

Definition at line 123 of file RestHandler.h.

◆ _mcch

ChannelInfo RestHandler::_mcch

RX info for MCCH.

Definition at line 103 of file RestHandler.h.

◆ _mch

std::map<uint32_t, ChannelInfo> RestHandler::_mch

RX info for MCHs.

Definition at line 108 of file RestHandler.h.

◆ _pdsch

ChannelInfo RestHandler::_pdsch

RX info for PDSCH.

Definition at line 98 of file RestHandler.h.

◆ _phy

Phy& RestHandler::_phy
private

Definition at line 127 of file RestHandler.h.

◆ _require_bearer_token

bool RestHandler::_require_bearer_token = false
private

Definition at line 131 of file RestHandler.h.

◆ _sdr

SdrReader& RestHandler::_sdr
private

Definition at line 126 of file RestHandler.h.

◆ _set_params

set_params_t RestHandler::_set_params
private

Definition at line 129 of file RestHandler.h.

◆ _state

state_t& RestHandler::_state
private

Definition at line 125 of file RestHandler.h.


The documentation for this class was generated from the following files: