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",
~BlackboardRestApi()
Destructor.
Interface field iterator.
void set_writer(const std::string &writer)
Set writer value.
void set_kind(const std::string &kind)
Set kind value.
BlackboardRestApi()
Constructor.
Webview REST API component.
std::string writer() const
Get owner name of writing interface instance.
const char * type() const
Get interface type.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
uint16_t get_uint16(unsigned int index=0) const
Get value of current field as unsigned integer.
int32_t * get_enums() const
Get value of current enum field as integer array.
void set_type(const std::string &type)
Set type value.
void set_name(const std::string &name)
Set name value.
const char * str(bool utc=false) const
Output function.
std::string hash_printable() const
Get interface version hash in printable format.
const char * get_typename() const
Get type of current field as string.
double get_double(unsigned int index=0) const
Get value of current field as double.
void set_name(const std::string &name)
Set name value.
REST processing exception.
void set_dotgraph(const std::string &dotgraph)
Set dotgraph value.
Fawkes library namespace.
bool get_bool(unsigned int index=0) const
Get value of current field as bool.
8 bit unsigned integer field
16 bit unsigned integer field
std::string str_join(const InputIterator &first, const InputIterator &last, char delim='/')
Join list of strings string using given delimiter.
const char * id() const
Get identifier of interface.
interface_fieldtype_t get_type() const
Get type of current field.
void set_enums(const std::vector< std::string > &enums)
Set enums value.
bool has_writer() const
Check if there is a writer.
void set_fields(const std::vector< std::shared_ptr< InterfaceFieldType >> &fields)
Set fields value.
byte field, alias for uint8
const char * get_value_string(const char *array_sep=", ")
Get value of current field as string.
Thread class encapsulation of pthreads.
virtual void finalize()
Finalize the thread.
float get_float(unsigned int index=0) const
Get value of current field as float.
void unregister_api(WebviewRestApi *api)
Remove a request processor.
virtual Message * create_message(const char *type) const =0
Create message based on type name.
Base class for all Fawkes BlackBoard interfaces.
Logger * logger
This is the Logger member used to access the logger.
InterfaceFieldIterator fields_end()
Invalid iterator.
virtual InterfaceInfoList * list(const char *type_pattern, const char *id_pattern)=0
Get list of interfaces matching type and ID patterns.
void set_apiVersion(const std::string &apiVersion)
Set apiVersion value.
const std::list< std::string > & readers() const
Get readers of interface.
void register_api(WebviewRestApi *api)
Add a REST API.
uint8_t get_byte(unsigned int index=0) const
Get value of current field as byte.
int16_t get_int16(unsigned int index=0) const
Get value of current field as integer.
void set_data(const std::shared_ptr< rapidjson::Document > &data)
Set data value.
void set_pretty_json(bool pretty)
Enable or disable pretty printed results.
Interface information list.
void add_handler(WebRequest::Method method, std::string path, Handler handler)
Add handler function.
static std::string api_version()
Get version of implemented API.
InterfaceData representation for JSON transfer.
const char * type() const
Get type of interface.
int8_t get_int8(unsigned int index=0) const
Get value of current field as integer.
Base class for exceptions in Fawkes.
REST parameters to pass to handlers.
void read()
Read from BlackBoard into local copy.
const char * get_name() const
Get name of current field.
const std::string & writer() const
Get name of writer on interface.
static std::string api_version()
Get version of implemented API.
uint8_t get_uint8(unsigned int index=0) const
Get value of current field as unsigned integer.
void push_back(M &m)
Add item at the back of the container.
bool has_writer() const
Check if there is a writer for the interface.
bool has_query_arg(const std::string &what)
Check if query argument is set.
const char * id() const
Get interface ID.
const char * name() const
Get name of thread.
virtual const char * what_no_backtrace() const
Get primary string (does not implicitly print the back trace).
void set_type(const std::string &type)
Set type value.
uint64_t get_uint64(unsigned int index=0) const
Get value of current field as unsigned integer.
64 bit unsigned integer field
const char * get_string() const
Get value of current field as string.
InterfaceFieldIterator fields()
Get iterator over all fields of this interface instance.
uint32_t get_uint32(unsigned int index=0) const
Get value of current field as unsigned integer.
const Time * timestamp() const
Get timestamp of last write.
size_t get_length() const
Get length of current field.
BlackboardGraph representation for JSON transfer.
void set_timestamp(const std::string ×tamp)
Set timestamp value.
virtual const char * enum_tostring(const char *enumtype, int val) const =0
Convert arbitrary enum value to string.
InterfaceFieldIterator fields_end()
Invalid iterator.
virtual void init()
Initialize the thread.
Container to return array via REST.
virtual InterfaceInfoList * list_all()=0
Get list of all currently existing interfaces.
void set_id(const std::string &id)
Set id value.
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
void set_kind(const std::string &kind)
Set kind value.
WebviewRestApiManager * webview_rest_api_manager
Webview REST API manager.
virtual void loop()
Code to execute in the thread.
std::string path_arg(const std::string &what)
Get a path argument.
void set_apiVersion(const std::string &apiVersion)
Set apiVersion value.
InterfaceFieldIterator fields()
Get iterator over all fields of this interface instance.
int32_t get_int32(unsigned int index=0) const
Get value of current field as integer.
void set_readers(const std::vector< std::string > &readers)
Set readers value.
std::list< std::string > readers() const
Get owner names of reading interface instances.
void set_is_array(const bool &is_array)
Set is_array value.
32 bit unsigned integer field
field with interface specific enum type
std::list< const char * > get_message_types()
Obtain a list of textual representations of the message types available for this interface.
static std::string api_version()
Get version of implemented API.
BlackBoard * blackboard
This is the BlackBoard instance you can use to interact with the BlackBoard.
virtual void close(Interface *interface)=0
Close interface.
int64_t get_int64(unsigned int index=0) const
Get value of current field as integer.