22 #include "blackboard-rest-api.h"
24 #include <core/threading/mutex_locker.h>
25 #include <interface/interface.h>
26 #include <interface/message.h>
27 #include <rapidjson/document.h>
28 #include <utils/time/wait.h>
29 #include <webview/rest_api_manager.h>
55 WebRequest::METHOD_GET,
"/interfaces", std::bind(&BlackboardRestApi::cb_list_interfaces,
this));
57 "/interfaces/{type}/{id+}/data",
58 std::bind(&BlackboardRestApi::cb_get_interface_data,
60 std::placeholders::_1));
62 "/interfaces/{type}/{id+}",
63 std::bind(&BlackboardRestApi::cb_get_interface_info,
65 std::placeholders::_1));
68 std::bind(&BlackboardRestApi::cb_get_graph,
this));
84 std::vector<std::shared_ptr<InterfaceFieldType>>
88 std::vector<std::shared_ptr<InterfaceFieldType>> rv;
89 for (
auto i = begin; i != end; ++i) {
90 std::shared_ptr<InterfaceFieldType> ft = std::make_shared<InterfaceFieldType>();
95 std::list<const char *> enum_values = i.get_enum_valuenames();
96 ft->
set_enums(std::vector<std::string>{std::begin(enum_values), std::end(enum_values)});
107 info.set_kind(
"InterfaceInfo");
109 info.set_id(ii.
id());
110 info.set_type(ii.
type());
113 info.set_writer(ii.
writer());
115 std::list<std::string> readers = ii.
readers();
116 info.set_readers(std::vector<std::string>{std::begin(readers), std::end(readers)});
118 if (type_info_cache_.find(ii.
type()) != type_info_cache_.end()) {
119 info.set_fields(type_info_cache_[ii.
type()].first);
120 info.set_message_types(type_info_cache_[ii.
type()].second);
125 std::vector<std::shared_ptr<InterfaceFieldType>> fields =
128 info.set_fields(fields);
130 std::vector<std::shared_ptr<InterfaceMessageType>> message_types;
133 for (
auto mt : message_type_names) {
135 std::shared_ptr<InterfaceMessageType> m = std::make_shared<InterfaceMessageType>();
138 message_types.push_back(m);
143 info.set_message_types(message_types);
144 type_info_cache_[ii.
type()] = std::make_pair(fields, message_types);
149 #define FIELD_ARRAY_CASE(TYPE, type, ctype) \
151 const ctype *values = i.get_##type##s(); \
152 for (unsigned int j = 0; j < i.get_length(); ++j) { \
153 value.PushBack(rapidjson::Value{values[j]}.Move(), allocator); \
158 static rapidjson::Value
161 rapidjson::Document::AllocatorType &allocator)
163 rapidjson::Value value;
167 value.SetString(std::string(i.
get_string()), allocator);
173 FIELD_ARRAY_CASE(BOOL,
bool,
bool);
174 FIELD_ARRAY_CASE(INT8, int8, int8_t);
175 FIELD_ARRAY_CASE(UINT8, uint8, uint8_t);
176 FIELD_ARRAY_CASE(INT16, int16, int16_t);
177 FIELD_ARRAY_CASE(UINT16, uint16, uint16_t);
178 FIELD_ARRAY_CASE(INT32, int32, int32_t);
179 FIELD_ARRAY_CASE(UINT32, uint32, uint32_t);
180 FIELD_ARRAY_CASE(INT64, int64, int64_t);
181 FIELD_ARRAY_CASE(UINT64, uint64, uint64_t);
182 FIELD_ARRAY_CASE(FLOAT,
float,
float);
183 FIELD_ARRAY_CASE(DOUBLE,
double,
double);
184 FIELD_ARRAY_CASE(BYTE,
byte, uint8_t);
188 for (
unsigned int j = 0; j < i.
get_length(); ++j) {
221 BlackboardRestApi::gen_interface_data(
Interface *iface,
bool pretty)
231 std::list<std::string> readers = iface->
readers();
232 data.
set_readers(std::vector<std::string>{std::begin(readers), std::end(readers)});
236 std::shared_ptr<rapidjson::Document> d = std::make_shared<rapidjson::Document>();
237 rapidjson::Document::AllocatorType & allocator = d->GetAllocator();
242 d->AddMember(
name.Move(), gen_field_value(i, iface, allocator).Move(), allocator);
250 BlackboardRestApi::cb_list_interfaces()
256 for (
const auto &ii : *ifls) {
266 if (params.
path_arg(
"type").find_first_of(
"*?") != std::string::npos) {
269 if (params.
path_arg(
"id").find_first_of(
"*?") != std::string::npos) {
273 std::unique_ptr<InterfaceInfoList> ifls{
276 if (ifls->size() < 1) {
278 "Interface %s:%s not found",
282 return gen_interface_info(ifls->front());
291 if (params.
path_arg(
"type").find_first_of(
"*?") != std::string::npos) {
294 if (params.
path_arg(
"id").find_first_of(
"*?") != std::string::npos) {
298 std::unique_ptr<InterfaceInfoList> ifls{
300 if (ifls->size() == 0) {
302 "Interface %s::%s: is currently not available",
314 "Failed to open %s::%s: %s",
327 "Failed to read %s:%s: %s",
335 BlackboardRestApi::generate_graph(
const std::string &for_owner)
340 std::stringstream mstream;
341 mstream <<
"digraph bbmap {" << std::endl <<
" graph [fontsize=12,rankdir=LR];" << std::endl;
343 std::set<std::string> owners;
345 InterfaceInfoList::iterator ii;
346 for (ii = iil->begin(); ii != iil->end(); ++ii) {
347 const std::list<std::string> readers = ii->readers();
349 if (for_owner ==
"" || ii->writer() == for_owner
350 || std::find_if(readers.begin(), readers.end(), [&for_owner](
const std::string &o) ->
bool {
351 return for_owner == o;
352 }) != readers.end()) {
353 if (ii->has_writer()) {
354 const std::string writer = ii->writer();
356 owners.insert(writer);
358 std::list<std::string>::const_iterator r;
359 for (r = readers.begin(); r != readers.end(); ++r) {
365 mstream <<
" node [fontsize=12 shape=box width=4 margin=0.05];" << std::endl
366 <<
" { rank=same; " << std::endl;
367 std::set<std::string>::iterator i;
368 for (ii = iil->begin(); ii != iil->end(); ++ii) {
369 const std::list<std::string> readers = ii->readers();
370 if (for_owner ==
"" || ii->writer() == for_owner
371 || std::find_if(readers.begin(), readers.end(), [&for_owner](
const std::string &o) ->
bool {
372 return for_owner == o;
373 }) != readers.end()) {
374 mstream <<
" \"" << ii->type() <<
"::" << ii->id() <<
"\""
375 <<
" [href=\"/blackboard/view/" << ii->type() <<
"::" << ii->id() <<
"\"";
377 if (!ii->has_writer()) {
378 mstream <<
" color=red";
379 }
else if (ii->writer().empty()) {
380 mstream <<
" color=purple";
382 mstream <<
"];" << std::endl;
385 mstream <<
" }" << std::endl;
387 mstream <<
" node [fontsize=12 shape=octagon width=3];" << std::endl;
388 for (i = owners.begin(); i != owners.end(); ++i) {
389 mstream <<
" \"" << *i <<
"\""
390 <<
" [href=\"/blackboard/graph/" << *i <<
"\"];" << std::endl;
393 for (ii = iil->begin(); ii != iil->end(); ++ii) {
394 const std::list<std::string> readers = ii->readers();
395 if (for_owner ==
"" || ii->writer() == for_owner
396 || std::find_if(readers.begin(), readers.end(), [&for_owner](
const std::string &o) ->
bool {
397 return for_owner == o;
398 }) != readers.end()) {
399 std::list<std::string> quoted_readers;
400 std::for_each(readers.begin(), readers.end(), ["ed_readers](
const std::string &r) {
401 quoted_readers.push_back(std::string(
"\"") + r +
"\"");
403 std::string quoted_readers_s =
str_join(quoted_readers,
' ');
404 mstream <<
" \"" << ii->type() <<
"::" << ii->id() <<
"\" -> { " << quoted_readers_s
405 <<
" } [style=dashed arrowhead=dot arrowsize=0.5 dir=both];" << std::endl;
407 if (ii->has_writer()) {
408 mstream <<
" \"" << (ii->writer().empty() ?
"???" : ii->writer()) <<
"\" -> \""
409 << ii->type() <<
"::" << ii->id() <<
"\""
410 << (ii->writer().empty() ?
" [color=purple]" :
" [color=\"#008800\"]") <<
";"
419 return mstream.str();
423 BlackboardRestApi::cb_get_graph()
433 "Failed to retrieve blackboard graph: %s",