22#include <blackboard/remote.h>
23#include <plugins/openprs/mod_utils.h>
24#include <utils/misc/string_conversions.h>
25#include <utils/time/time.h>
27#include <lisp-list_f-pub.h>
28#include <oprs-array_f-pub.h>
29#include <oprs-type_f-pub.h>
30#include <oprs_f-pub.h>
31#include <slistPack_f.h>
35extern "C" void finalize();
39std::map<std::string, Interface *> g_interfaces_read;
40std::map<std::string, Interface *> g_interfaces_write;
46action_blackboard_open(TermList terms)
48 int terms_len = sl_slist_length(terms);
51 "Error[bb-open-interface]: invalid number of "
52 "arguments: req 3, got %i\n",
57 Term *type = (Term *)get_list_pos(terms, 1);
58 Term *
id = (Term *)get_list_pos(terms, 2);
59 Term *mode = (Term *)get_list_pos(terms, 3);
60 if (type->type != STRING) {
61 fprintf(stderr,
"Error[bb-open-interface]: interface type is not a STRING\n");
64 if (id->type != STRING) {
65 fprintf(stderr,
"Error[bb-open-interface]: interface ID is not a STRING\n");
68 if (id->type != STRING) {
69 fprintf(stderr,
"Error[bb-open-interface]: interface ID is not a STRING\n");
72 if (mode->type != TT_ATOM) {
73 fprintf(stderr,
"Error[bb-open-interface]: interface mode is not a symbol\n");
76 if (mode->u.id != g_bb_read_sym && mode->u.id != g_bb_write_sym) {
77 fprintf(stderr,
"Error[bb-open-interface]: interface mode must be BB-READ or BB-WRITE\n");
81 std::string uid = std::string(type->u.string) +
"::" +
id->u.string;
83 if (mode->u.id == g_bb_read_sym) {
84 if (g_interfaces_read.find(uid) == g_interfaces_read.end()) {
86 printf(
"Opening interface %s::%s for reading\n", type->u.string, id->u.string);
88 g_interfaces_read[uid] = iface;
91 "Failed to open interface %s::%s: %s",
99 if (g_interfaces_write.find(uid) == g_interfaces_write.end()) {
101 printf(
"Opening interface %s::%s for writing\n", type->u.string, id->u.string);
103 g_interfaces_write[uid] = iface;
106 "Failed to open interface %s::%s: %s\n",
119action_blackboard_close(TermList terms)
121 int terms_len = sl_slist_length(terms);
122 if (terms_len != 2) {
124 "Error[bb-close-interface]: invalid number of "
125 "arguments: req 2, got %i\n",
130 Term *type = (Term *)get_list_pos(terms, 1);
131 Term *
id = (Term *)get_list_pos(terms, 2);
132 if (type->type != STRING) {
133 fprintf(stderr,
"Error[bb-close-interface]: interface type is not a STRING\n");
136 if (id->type != STRING) {
137 fprintf(stderr,
"Error[bb-close-interface]: interface ID is not a STRING\n");
140 if (id->type != STRING) {
141 fprintf(stderr,
"Error[bb-close-interface]: interface ID is not a STRING\n");
145 std::string uid = std::string(type->u.string) +
"::" +
id->u.string;
147 if (g_interfaces_read.find(uid) != g_interfaces_read.end()) {
149 printf(
"Closing reading interface %s::%s\n", type->u.string, id->u.string);
150 g_blackboard->
close(g_interfaces_read[uid]);
151 g_interfaces_read.erase(uid);
154 "Failed to close interface %s::%s: %s",
160 }
else if (g_interfaces_write.find(uid) != g_interfaces_write.end()) {
162 printf(
"Closing writing interface %s::%s\n", type->u.string, id->u.string);
163 g_blackboard->
close(g_interfaces_write[uid]);
164 g_interfaces_write.erase(uid);
167 "Failed to close interface %s::%s: %s\n",
179action_blackboard_print(TermList terms)
181 Term *type = (Term *)get_list_pos(terms, 1);
182 Term *
id = (Term *)get_list_pos(terms, 2);
183 if (type->type != STRING) {
184 fprintf(stderr,
"Error[bb-print]: interface type is not a STRING\n");
187 if (id->type != STRING) {
188 fprintf(stderr,
"Error[bb-print]: interface ID is not a STRING\n");
191 if (id->type != STRING) {
192 fprintf(stderr,
"Error[bb-print]: interface ID is not a STRING\n");
196 std::string uid = std::string(type->u.string) +
"::" +
id->u.string;
200 if (g_interfaces_read.find(uid) != g_interfaces_read.end()) {
201 i = g_interfaces_read[uid];
202 }
else if (g_interfaces_write.find(uid) != g_interfaces_write.end()) {
203 i = g_interfaces_write[uid];
205 fprintf(stderr,
"Error[bb-print]: interface %s has not been opened\n", uid.c_str());
206 fprintf(stderr,
"Error[bb-print]: Open interfaces are:\n");
207 for (
auto j : g_interfaces_read) {
208 fprintf(stderr,
"Error[bb-print]: [R] %s\n", j.second->uid());
210 for (
auto j : g_interfaces_write) {
211 fprintf(stderr,
"Error[bb-print]: [W] %s\n", j.second->uid());
213 fprintf(stderr,
"Error[bb-print]: -----\n");
221 std::string fact = std::string(
"(bb-data \"type\" \"") + i->
type() +
"\"" +
" \"id\" \""
222 + i->
id() +
"\"" +
" \"time\" " + StringConversions::to_string(t->
get_sec())
223 +
" " + StringConversions::to_string(t->
get_usec()) +
"" +
" (. ";
226 for (f = i->
fields(); f != f_end; ++f) {
230 std::string::size_type pos = 0;
231 while ((pos = value.find(
"\"", pos)) != std::string::npos) {
232 value.replace(pos, 1,
"\\\"");
235 value = std::string(
"\"") + value +
"\"";
236 }
else if (f.
get_type() == IFT_ENUM) {
240 std::string::size_type pos;
241 while ((pos = value.find(
",")) != std::string::npos) {
242 value = value.erase(pos, 1);
246 fact += std::string(
" \"") + f.
get_name() +
"\" [ " + value +
" ]";
248 fact += std::string(
" \"") + f.
get_name() +
"\" " + value;
253 printf(
"%s\n", fact.c_str());
261#define ADD_ARRAY(src_type, target_type, array_type) \
263 target_type * array = (target_type *)OPRS_MALLOC(sizeof(target_type) * f.get_length()); \
264 src_type##_t *src_array = f.get_##src_type##s(); \
265 for (unsigned int j = 0; j < f.get_length(); ++j) \
266 array[j] = src_array[j]; \
267 data = l_add_to_tail(data, make_##array_type##_array_from_array(f.get_length(), array)); \
270#define BUILD_FUNC(singular_type) build_##singular_type
271#define GET_FUNC(src_type) get_##src_type
273#define ADD_NUM_DATA(src_type, target_type, array_type, singular_type) \
275 if (f.get_length() > 1) { \
276 ADD_ARRAY(src_type, target_type, array_type); \
278 data = l_add_to_tail(data, BUILD_FUNC(singular_type)(f.GET_FUNC(src_type)())); \
289 TermList tl = sl_make_slist();
290 tl = build_term_list(tl, build_string(
"type"));
291 tl = build_term_list(tl, build_string(i->
type()));
292 tl = build_term_list(tl, build_string(
"id"));
293 tl = build_term_list(tl, build_string(i->
id()));
294 tl = build_term_list(tl, build_string(
"time"));
295 tl = build_term_list(tl, build_long_long(t->
get_sec()));
296 tl = build_term_list(tl, build_long_long(t->
get_usec()));
300 for (f = i->
fields(); f != f_end; ++f) {
301 data = l_add_to_tail(data, build_string(f.
get_name()));
305 data = l_add_to_tail(data, build_id(f.
get_bool() ? lisp_t_sym : nil_sym));
307 case IFT_INT8: ADD_NUM_DATA(int8,
int,
int, integer);
break;
308 case IFT_UINT8: ADD_NUM_DATA(uint8,
int,
int, integer);
break;
309 case IFT_INT16: ADD_NUM_DATA(int16,
int,
int, integer);
break;
310 case IFT_UINT16: ADD_NUM_DATA(uint16,
int,
int, integer);
break;
311 case IFT_INT32: ADD_NUM_DATA(int32,
int,
int, integer);
break;
312 case IFT_UINT32: ADD_NUM_DATA(uint32,
double,
float, long_long);
break;
313 case IFT_INT64: ADD_NUM_DATA(int64,
double,
float, long_long);
break;
314 case IFT_UINT64: ADD_NUM_DATA(uint64,
double,
float, long_long);
break;
315 case IFT_FLOAT: ADD_NUM_DATA(
float,
double,
float,
float);
break;
316 case IFT_DOUBLE: ADD_NUM_DATA(
double,
double,
float,
float);
break;
318 case IFT_BYTE: ADD_NUM_DATA(uint8,
int,
int, integer);
break;
323 tl = build_term_list(tl, build_l_list(data));
324 add_external_fact((
char *)
"bb-data", tl);
329action_blackboard_read_all(TermList terms)
332 for (
auto &if_entry : g_interfaces_read) {
344action_blackboard_read(TermList terms)
346 int terms_len = sl_slist_length(terms);
347 if (terms_len != 2) {
349 "Error[bb-read]: invalid number of "
350 "arguments: req 2, got %i\n",
355 Term *type = (Term *)get_list_pos(terms, 1);
356 Term *
id = (Term *)get_list_pos(terms, 2);
357 if (type->type != STRING) {
358 fprintf(stderr,
"Error[bb-read]: interface type is not a STRING\n");
361 if (id->type != STRING) {
362 fprintf(stderr,
"Error[bb-read]: interface ID is not a STRING\n");
365 if (id->type != STRING) {
366 fprintf(stderr,
"Error[bb-read]: interface ID is not a STRING\n");
370 std::string uid = std::string(type->u.string) +
"::" +
id->u.string;
372 if (g_interfaces_read.find(uid) != g_interfaces_read.end()) {
374 post_interface(g_interfaces_read[uid]);
377 "Failed to read interface %s::%s: %s",
385 "Failed to read interface %s::%s: interface not opened",
397func_blackboard_value(TermList terms)
399 int terms_len = sl_slist_length(terms);
400 if (terms_len != 2) {
402 "Error[bb-value]: invalid number of "
403 "arguments: req 2, got %i\n",
407 Term *dlist = (Term *)get_list_pos(terms, 1);
408 Term *name = (Term *)get_list_pos(terms, 2);
411 if (dlist->type != LISP_LIST) {
412 fprintf(stderr,
"Error[bb-value]: first argument is not a LISP_LIST\n");
415 if (name->type != STRING) {
416 fprintf(stderr,
"Error[bb-value]: interface ID is not a STRING\n");
419 char *pattern = name->u.string;
421 while (i < l_length(dlist->u.l_list) - 1) {
422 Term *t1 = get_term_from_l_car(l_nth(dlist->u.l_list, i));
423 if (t1->type == STRING) {
424 char *searched = t1->u.string;
425 if (strcmp(pattern, searched) == 0) {
426 restemp = get_term_from_l_car(l_nth((dlist->u).l_list, i + 1));
429 if (restemp->type == STRING) {
430 std::string outputs = std::string(restemp->u.string);
431 std::transform(outputs.begin(), outputs.end(), outputs.begin(), ::tolower);
432 restemp = build_id(declare_atom(outputs.c_str()));
434 return copy_term(restemp);
439 fprintf(stderr,
"Error[bb-value]: wanted entry in bb-data not present\n");
447 printf(
"*** LOADING mod_blackboard\n");
449 std::string fawkes_host;
450 unsigned short fawkes_port = 0;
451 get_fawkes_host_port(fawkes_host, fawkes_port);
453 printf(
"Connecting to Fawkes at %s:%u\n", fawkes_host.c_str(), fawkes_port);
457 fprintf(stderr,
"Error: cannot establish blackboard connection: %s\n", e.
what_no_backtrace());
460 g_bb_read_sym = declare_atom(
"BB-READ");
461 g_bb_write_sym = declare_atom(
"BB-WRITE");
462 g_bb_data_sym = declare_atom(
"bb-data");
463 declare_pred_from_symbol(g_bb_data_sym);
464 make_and_declare_eval_funct(
"bb-value", func_blackboard_value, 2);
465 make_and_declare_action(
"bb-open", action_blackboard_open, 3);
466 make_and_declare_action(
"bb-close", action_blackboard_close, 2);
467 make_and_declare_action(
"bb-read", action_blackboard_read, 2);
468 make_and_declare_action(
"bb-read-all", action_blackboard_read_all, 0);
469 make_and_declare_action(
"bb-print", action_blackboard_print, 2);
470 add_user_end_kernel_hook(finalize);
477 printf(
"*** DESTROYING mod_skiller\n");
478 for (
auto &iface : g_interfaces_read) {
479 g_blackboard->
close(iface.second);
481 g_interfaces_read.clear();
482 for (
auto &iface : g_interfaces_write) {
483 g_blackboard->
close(iface.second);
485 g_interfaces_write.clear();
The BlackBoard abstract class.
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
virtual Interface * open_for_writing(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for writing.
virtual void close(Interface *interface)=0
Close interface.
Base class for exceptions in Fawkes.
virtual const char * what_no_backtrace() const noexcept
Get primary string (does not implicitly print the back trace).
Interface field iterator.
size_t get_length() const
Get length of current field.
interface_fieldtype_t get_type() const
Get type of current field.
const char * get_name() const
Get name of current field.
bool get_bool(unsigned int index=0) const
Get value of current field as bool.
const char * get_value_string(const char *array_sep=", ")
Get value of current field as string.
Base class for all Fawkes BlackBoard interfaces.
const char * type() const
Get type of interface.
const Time * timestamp() const
Get timestamp of last write.
InterfaceFieldIterator fields_end()
Invalid iterator.
const char * id() const
Get identifier of interface.
InterfaceFieldIterator fields()
Get iterator over all fields of this interface instance.
void read()
Read from BlackBoard into local copy.
bool refreshed() const
Check if data has been refreshed.
A class for handling time.
long get_usec() const
Get microseconds.
long get_sec() const
Get seconds.
Fawkes library namespace.
@ IFT_INT8
8 bit integer field
@ IFT_UINT32
32 bit unsigned integer field
@ IFT_BYTE
byte field, alias for uint8
@ IFT_UINT64
64 bit unsigned integer field
@ IFT_UINT16
16 bit unsigned integer field
@ IFT_INT32
32 bit integer field
@ IFT_INT64
64 bit integer field
@ IFT_INT16
16 bit integer field
@ IFT_ENUM
field with interface specific enum type
@ IFT_UINT8
8 bit unsigned integer field