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