Fawkes API  Fawkes Development Version
blackboard.cpp
1 
2 /***************************************************************************
3  * blackboard.h - External predicates to remotely access the Fawkes
4  * blackboard
5  *
6  * Created: Wed Mar 09 17:10:54 2011
7  * Copyright 2011 Daniel Beck
8  * 2014 Tim Niemueller
9  ****************************************************************************/
10 
11 /* This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL file in the doc directory.
22  */
23 
24 #include "blackboard.h"
25 
26 #include <logging/logger.h>
27 #include <plugins/eclipse-clp/blackboard_listener_thread.h>
28 #include <plugins/eclipse-clp/eclipse_thread.h>
29 
30 #include <cstdlib>
31 #include <cstring>
32 
33 namespace fawkes {
34 /** @class fawkes::EclExternalBlackBoard
35  * Wrapper class for using the blackboard in the implementation of the external
36  * predicates.
37  * @author Daniel Beck
38  */
39 
40 BlackBoard * EclExternalBlackBoard::m_blackboard = NULL;
41 EclExternalBlackBoard *EclExternalBlackBoard::m_instance = NULL;
42 
43 /** Constructor. */
44 EclExternalBlackBoard::EclExternalBlackBoard(BlackBoard *blackboard, Logger *logger)
45 {
46  if (m_instance != NULL) {
47  throw Exception("There is already an instance of type "
48  "EclExternalBlackBoard instantiated");
49  }
50  m_blackboard = blackboard;
51  m_logger = logger;
52 }
53 
54 /** Destructor. */
56 {
57 }
58 
59 /** Creates the initial EclExternalBlackBoard object
60  * @param bb pointer to the BlackBoard to be used
61  * @param logger pointer to the Logger to be used
62  */
63 void
65 {
66  m_instance = new EclExternalBlackBoard(bb, logger);
67 }
68 
69 /** Delete the current EclExternalBlackBoard instance and set it to NULL */
70 void
72 {
73  if (m_instance) {
74  delete m_instance;
75  }
76  m_instance = NULL;
77 }
78 
79 /** Get the EclExternalBlackBoard instance.
80  * @return the instance
81  */
84 {
85  return m_instance;
86 }
87 
88 /** Access the BlackBoard instance.
89  * @return the blackboard instance
90  */
91 BlackBoard *
93 {
94  return m_blackboard;
95 }
96 
97 /** Obtain the list of opened interfaces.
98  * @return list of opened interfaces
99  */
100 std::map<std::string, Interface *> &
102 {
103  return m_interfaces;
104 }
105 
106 } // namespace fawkes
107 
108 using namespace fawkes;
109 
110 bool process_message_args(Message *msg, EC_word arg_list);
111 
112 int
113 p_bb_open_interface()
114 {
115  EC_atom mode;
116  char * interface_type;
117  char * interface_id;
118 
119  if (EC_succeed != EC_arg(1).is_atom(&mode)) {
120  fprintf(stderr, "p_bb_open_interface(): no mode given\n");
121  return EC_fail;
122  }
123 
124  if (EC_succeed != EC_arg(2).is_string(&interface_type)) {
125  fprintf(stderr, "p_bb_open_interface(): no type given\n");
126  return EC_fail;
127  }
128 
129  if (EC_succeed != EC_arg(3).is_string(&interface_id)) {
130  fprintf(stderr, "p_bb_open_interface(): no id given\n");
131  return EC_fail;
132  }
133 
134  std::map<std::string, Interface *> &interfaces = EclExternalBlackBoard::instance()->interfaces();
135 
136  std::string uid = std::string(interface_type) + "::" + interface_id;
137  if (interfaces.find(uid) == interfaces.end()) {
138  try {
139  Interface *iface;
140 
141  if (0 == strcmp("w", mode.name())) {
142  iface =
144  interface_id);
145  } else {
146  iface =
148  interface_id);
149  }
150 
151  interfaces[iface->uid()] = iface;
152  } catch (Exception &e) {
153  fprintf(stderr, "p_bb_open_interface() failed: %s\n", e.what_no_backtrace());
154  return EC_fail;
155  }
156  }
157 
158  if (interfaces.find(uid) == interfaces.end()) {
159  return EC_fail;
160  }
161 
162  return EC_succeed;
163 }
164 
165 int
166 p_bb_close_interface()
167 {
168  char *uid;
169 
170  if (EC_succeed != EC_arg(1).is_string(&uid)) {
171  fprintf(stderr, "p_bb_close_interface(): no id given\n");
172  return EC_fail;
173  }
174 
175  std::map<std::string, Interface *> &interfaces = EclExternalBlackBoard::instance()->interfaces();
176 
177  if (interfaces.find(uid) != interfaces.end()) {
180  }
181 
182  return EC_succeed;
183 }
184 
185 int
186 p_bb_has_writer()
187 {
188  char *uid;
189 
190  if (EC_succeed != EC_arg(1).is_string(&uid)) {
191  fprintf(stderr, "p_bb_has_writer(): no uid given\n");
192  return EC_fail;
193  }
194 
195  std::map<std::string, Interface *> &interfaces = EclExternalBlackBoard::instance()->interfaces();
196 
197  if (interfaces.find(uid) != interfaces.end()) {
198  return interfaces[uid]->has_writer() ? EC_succeed : EC_fail;
199  }
200 
201  return EC_fail;
202 }
203 
204 int
205 p_bb_instance_serial()
206 {
207  char *uid;
208  if (EC_succeed != EC_arg(1).is_string(&uid)) {
209  fprintf(stderr, "p_bb_instance_serial(): no interface uid given\n");
210  return EC_fail;
211  }
212 
213  std::map<std::string, Interface *> &interfaces = EclExternalBlackBoard::instance()->interfaces();
214 
215  if (interfaces.find(uid) != interfaces.end()) {
216  if (EC_succeed != EC_arg(2).unify(interfaces[uid]->serial().get_string().c_str())) {
217  fprintf(stderr, "p_bb_instance_serial(): could not bind return value\n");
218  return EC_fail;
219  } else {
220  return EC_succeed;
221  }
222  }
223 
224  return EC_fail;
225 }
226 
227 int
228 p_bb_read_interfaces()
229 {
230  for (std::map<std::string, Interface *>::iterator it =
231  EclExternalBlackBoard::instance()->interfaces().begin();
233  ++it) {
234  it->second->read();
235  }
236 
237  return EC_succeed;
238 }
239 
240 int
241 p_bb_read_interface()
242 {
243  char *uid;
244  if (EC_succeed != EC_arg(1).is_string(&uid)) {
245  fprintf(stderr, "p_read_interface(): no interface UID given\n");
246  return EC_fail;
247  }
248 
249  std::map<std::string, Interface *> &interfaces = EclExternalBlackBoard::instance()->interfaces();
250 
251  if (interfaces.find(uid) == interfaces.end()) {
252  fprintf(stderr, "p_bb_read_interface: interface %s has not been opened\n", uid);
253  return EC_fail;
254  }
255 
256  interfaces[uid]->read();
257 
258  return EC_succeed;
259 }
260 
261 int
262 p_bb_write_interfaces()
263 {
264  for (std::map<std::string, Interface *>::iterator it =
265  EclExternalBlackBoard::instance()->interfaces().begin();
267  ++it) {
268  if (it->second->is_writer()) {
269  it->second->write();
270  }
271  }
272 
273  return EC_succeed;
274 }
275 
276 int
277 p_bb_write_interface()
278 {
279  char *uid;
280  if (EC_succeed != EC_arg(1).is_string(&uid)) {
281  fprintf(stderr, "p_read_interface(): no interface UID given\n");
282  return EC_fail;
283  }
284 
285  std::map<std::string, Interface *> &interfaces = EclExternalBlackBoard::instance()->interfaces();
286 
287  if (interfaces.find(uid) == interfaces.end()) {
288  fprintf(stderr, "p_bb_read_interface: interface %s has not been opened\n", uid);
289  return EC_fail;
290  }
291 
292  if (!interfaces[uid]->is_writer()) {
293  fprintf(stderr, "p_bb_set(): interface %s not a writer\n", uid);
294  return EC_fail;
295  }
296 
297  interfaces[uid]->write();
298  return EC_succeed;
299 }
300 
301 int
302 p_bb_interface_changed()
303 {
304  char *uid;
305  if (EC_succeed != EC_arg(1).is_string(&uid)) {
306  fprintf(stderr, "p_interface_changed(): no interface UID given\n");
307  return EC_fail;
308  }
309 
310  std::map<std::string, Interface *> &interfaces = EclExternalBlackBoard::instance()->interfaces();
311 
312  if (interfaces.find(uid) == interfaces.end()) {
313  fprintf(stderr, "p_bb_interface_changed: interface %s has not been opened\n", uid);
314  return EC_fail;
315  }
316 
317  return interfaces[uid]->refreshed() ? EC_succeed : EC_fail;
318 }
319 
320 int
321 p_bb_get()
322 {
323  char *uid;
324  char *field;
325 
326  if (EC_succeed != EC_arg(1).is_string(&uid)) {
327  fprintf(stderr, "p_bb_get(): no interface uid given\n");
328  return EC_fail;
329  }
330 
331  if (EC_succeed != EC_arg(2).is_string(&field)) {
332  fprintf(stderr, "p_bb_get(): no field given\n");
333  return EC_fail;
334  }
335 
336  std::map<std::string, Interface *> &interfaces = EclExternalBlackBoard::instance()->interfaces();
337 
338  if (interfaces.find(uid) != interfaces.end()) {
339  Interface *iface = interfaces[uid];
340 
342  for (fit = iface->fields(); fit != iface->fields_end(); ++fit) {
343  if (0 == strcmp(field, fit.get_name())) {
344  switch (fit.get_type()) {
345  case IFT_BOOL:
346  if (fit.get_bool()) {
347  if (EC_succeed != EC_arg(3).unify(EC_atom((char *)"true"))) {
348  fprintf(stderr, "p_bb_get(): could not bind return value\n");
349  return EC_fail;
350  }
351  } else {
352  if (EC_succeed != EC_arg(3).unify(EC_atom((char *)"false"))) {
353  fprintf(stderr, "p_bb_get(): could not bind return value\n");
354  return EC_fail;
355  }
356  }
357  break;
358 
359  case IFT_INT8:
360  if (EC_succeed != EC_arg(3).unify(EC_word((long)fit.get_int8()))) {
361  fprintf(stderr, "p_bb_get(): could not bind return value\n");
362  return EC_fail;
363  }
364  break;
365 
366  case IFT_UINT8:
367  if (EC_succeed != EC_arg(3).unify(EC_word((long)fit.get_uint8()))) {
368  fprintf(stderr, "p_bb_get(): could not bind return value\n");
369  return EC_fail;
370  }
371  break;
372 
373  case IFT_INT16:
374  if (EC_succeed != EC_arg(3).unify(EC_word((long)fit.get_int16()))) {
375  fprintf(stderr, "p_bb_get(): could not bind return value\n");
376  return EC_fail;
377  }
378  break;
379 
380  case IFT_UINT16:
381  if (EC_succeed != EC_arg(3).unify(EC_word((long)fit.get_uint16()))) {
382  fprintf(stderr, "p_bb_get(): could not bind return value\n");
383  return EC_fail;
384  }
385  break;
386 
387  case IFT_INT32:
388  if (EC_succeed != EC_arg(3).unify(EC_word((long)fit.get_int32()))) {
389  fprintf(stderr, "p_bb_get: could not bind value\n");
390  return EC_fail;
391  }
392  break;
393 
394  case IFT_UINT32:
395  if (EC_succeed != EC_arg(3).unify(EC_word((long)fit.get_uint32()))) {
396  fprintf(stderr, "p_bb_get(): could not bind return value\n");
397  return EC_fail;
398  }
399  break;
400 
401  case IFT_INT64:
402  if (EC_succeed != EC_arg(3).unify(EC_word((long)fit.get_int64()))) {
403  fprintf(stderr, "p_bb_get(): could not bind return value\n");
404  return EC_fail;
405  }
406  break;
407 
408  case IFT_UINT64:
409  if (EC_succeed != EC_arg(3).unify(EC_word((long)fit.get_uint64()))) {
410  fprintf(stderr, "p_bb_get(): could not bind return value\n");
411  return EC_fail;
412  }
413  break;
414 
415  case IFT_FLOAT:
416  if (fit.get_length() > 1) {
417  EC_word res = nil();
418  float * f_array = fit.get_floats();
419  for (int i = fit.get_length() - 1; i >= 0; --i)
420  res = ::list(EC_word(f_array[i]), res);
421  if (EC_succeed != EC_arg(3).unify(res)) {
422  fprintf(stderr, "p_bb_get(): could not bind return value\n");
423  return EC_fail;
424  }
425  } else {
426  if (EC_succeed != EC_arg(3).unify(EC_word((double)fit.get_float()))) {
427  fprintf(stderr, "p_bb_get(): could not bind return value\n");
428  return EC_fail;
429  }
430  }
431  break;
432 
433  case IFT_DOUBLE:
434  if (fit.get_length() > 1) {
435  EC_word res = nil();
436  double *double_array = fit.get_doubles();
437  for (int i = fit.get_length() - 1; i >= 0; --i)
438  res = ::list(EC_word(double_array[i]), res);
439  if (EC_succeed != EC_arg(3).unify(res)) {
440  fprintf(stderr, "p_bb_get(): could not bind return value\n");
441  return EC_fail;
442  }
443  } else {
444  if (EC_succeed != EC_arg(3).unify(EC_word((double)fit.get_double()))) {
445  fprintf(stderr, "p_bb_get(): could not bind return value\n");
446  return EC_fail;
447  }
448  }
449  break;
450 
451  case IFT_STRING:
452  if (EC_succeed != EC_arg(3).unify(EC_word(fit.get_string()))) {
453  fprintf(stderr, "p_bb_get(): could not bind return value\n");
454  return EC_fail;
455  }
456  break;
457 
458  case IFT_BYTE:
459  if (fit.get_length() > 1) {
460  EC_word res = nil();
461  uint8_t *array = fit.get_bytes();
462  for (int i = fit.get_length() - 1; i >= 0; i--)
463  res = ::list(EC_word((long)array[i]), res);
464  if (EC_succeed != EC_arg(3).unify(res)) {
465  printf("p_bb_get(): could not bind return value\n");
466  return EC_fail;
467  }
468  } else {
469  if (EC_succeed != EC_arg(3).unify(EC_word((long)fit.get_byte()))) {
470  printf("p_bb_get(): could not bind return value\n");
471  return EC_fail;
472  }
473  }
474  break;
475 
476  case IFT_ENUM:
477  if (EC_succeed != EC_arg(3).unify(fit.get_value_string())) {
478  fprintf(stderr, "p_bb_get(): could not bind return value\n");
479  return EC_fail;
480  }
481  break;
482 
483  default:
484  fprintf(stderr,
485  "p_bb_get(): could not find type of interface! Type: %s (%d)",
486  fit.get_typename(),
487  fit.get_type());
488  break;
489  }
490  break;
491  }
492  }
493 
494  if (fit == iface->fields_end()) {
495  fprintf(stderr, "p_bb_get(): interface %s has no field %s\n", uid, field);
496  return EC_fail;
497  }
498 
499  } else {
500  fprintf(stderr, "p_bb_get(): no interface with id %s found\n", uid);
501  return EC_fail;
502  }
503 
504  return EC_succeed;
505 }
506 
507 int
508 p_bb_set()
509 {
510  char *uid;
511  char *field;
512 
513  if (EC_succeed != EC_arg(1).is_string(&uid)) {
514  fprintf(stderr, "p_bb_set(): no interface id given\n");
515  return EC_fail;
516  }
517 
518  if (EC_succeed != EC_arg(2).is_string(&field)) {
519  fprintf(stderr, "p_bb_set(): no field given\n");
520  return EC_fail;
521  }
522 
523  std::map<std::string, Interface *> &interfaces = EclExternalBlackBoard::instance()->interfaces();
524 
525  if (interfaces.find(uid) != interfaces.end()) {
526  Interface *iface = interfaces[uid];
527 
528  if (!iface->is_writer()) {
529  fprintf(stderr, "p_bb_set(): interface %s not a writer\n", uid);
530  return EC_fail;
531  }
532 
534  for (fit = iface->fields(); fit != iface->fields_end(); ++fit) {
535  if (0 == strcmp(field, fit.get_name())) {
536  switch (fit.get_type()) {
537  case IFT_BOOL: {
538  EC_atom val;
539  if (EC_succeed != EC_arg(3).is_atom(&val)) {
540  fprintf(stderr, "p_bb_set(): no value_given\n");
541  return EC_fail;
542  }
543 
544  if (0 == strcmp("true", val.name())) {
545  fit.set_bool(true);
546  } else if (0 == strcmp("false", val.name())) {
547  fit.set_bool(false);
548  } else {
549  fprintf(stderr, "p_bb_set(): boolean value neither true nor false\n");
550  return EC_fail;
551  }
552  } break;
553 
554  case IFT_INT8: {
555  long val;
556  if (EC_succeed != EC_arg(3).is_long(&val)) {
557  fprintf(stderr, "p_bb_set(): no value given\n");
558  return EC_fail;
559  }
560 
561  fit.set_int8((int8_t)val);
562  } break;
563 
564  case IFT_UINT8: {
565  long val;
566  if (EC_succeed != EC_arg(3).is_long(&val)) {
567  fprintf(stderr, "p_bb_set(): no value given\n");
568  return EC_fail;
569  }
570 
571  fit.set_uint8((uint8_t)val);
572  } break;
573 
574  case IFT_INT16: {
575  long val;
576  if (EC_succeed != EC_arg(3).is_long(&val)) {
577  fprintf(stderr, "p_bb_set(): no value given\n");
578  return EC_fail;
579  }
580 
581  fit.set_int16((int16_t)val);
582  } break;
583 
584  case IFT_UINT16: {
585  long val;
586  if (EC_succeed != EC_arg(3).is_long(&val)) {
587  fprintf(stderr, "p_bb_set(): no value given\n");
588  return EC_fail;
589  }
590 
591  fit.set_uint16((uint16_t)val);
592  } break;
593 
594  case IFT_INT32: {
595  long val;
596  if (EC_succeed != EC_arg(3).is_long(&val)) {
597  fprintf(stderr, "p_bb_set(): no value given\n");
598  return EC_fail;
599  }
600 
601  fit.set_int32((int32_t)val);
602  } break;
603 
604  case IFT_UINT32: {
605  long val;
606  if (EC_succeed != EC_arg(3).is_long(&val)) {
607  fprintf(stderr, "p_bb_set(): no value given\n");
608  return EC_fail;
609  }
610 
611  fit.set_uint32((uint32_t)val);
612  } break;
613 
614  case IFT_INT64: {
615  long val;
616  if (EC_succeed != EC_arg(3).is_long(&val)) {
617  fprintf(stderr, "p_bb_set(): no value given\n");
618  return EC_fail;
619  }
620 
621  fit.set_int64((int64_t)val);
622  } break;
623 
624  case IFT_UINT64: {
625  long val;
626  if (EC_succeed != EC_arg(3).is_long(&val)) {
627  fprintf(stderr, "p_bb_set(): no value given\n");
628  return EC_fail;
629  }
630 
631  fit.set_uint64((uint64_t)val);
632  } break;
633 
634  case IFT_FLOAT: {
635  double val;
636  if (EC_succeed != EC_arg(3).is_double(&val)) {
637  fprintf(stderr, "p_bb_set(): no value given\n");
638  return EC_fail;
639  }
640 
641  fit.set_float((float)val);
642  } break;
643 
644  case IFT_STRING: {
645  char *val;
646  if (EC_succeed != EC_arg(3).is_string(&val)) {
647  fprintf(stderr, "p_bb_set(): no value given\n");
648  return EC_fail;
649  }
650 
651  fit.set_string(val);
652  } break;
653 
654  case IFT_BYTE:
655  case IFT_ENUM: fprintf(stderr, "p_bb_set(): NOT YET IMPLEMENTET\n"); break;
656 
657  default: break;
658  }
659  break;
660  }
661  }
662 
663  if (fit == iface->fields_end()) {
664  fprintf(stderr, "p_bb_set(): interface %s has no field %s\n", uid, field);
665  return EC_fail;
666  }
667 
668  } else {
669  fprintf(stderr, "p_bb_set(): no interface with id %s found\n", uid);
670 
671  return EC_fail;
672  }
673 
674  return EC_succeed;
675 }
676 
677 int
678 p_bb_send_message()
679 {
680  char *uid;
681  char *message_type;
682 
683  if (EC_succeed != EC_arg(1).is_string(&uid)) {
684  fprintf(stderr, "p_bb_send_message(): no interface id given\n");
685  return EC_fail;
686  }
687 
688  if (EC_succeed != EC_arg(2).is_string(&message_type)) {
689  fprintf(stderr, "p_bb_send_message(): no message type given\n");
690  return EC_fail;
691  }
692 
693  std::map<std::string, Interface *> &interfaces = EclExternalBlackBoard::instance()->interfaces();
694 
695  if (interfaces.find(uid) != interfaces.end()) {
696  Interface *iface = interfaces[uid];
697 
698  if (iface->is_writer()) {
699  fprintf(stderr, "p_bb_send_message(): interface with uid %s is a writer\n", uid);
700  return EC_fail;
701  }
702 
703  try {
704  Message *msg = iface->create_message(message_type);
705 
706  EC_word head;
707  EC_word tail;
708  if (EC_succeed == EC_arg(3).is_list(head, tail)) {
709  if (!process_message_args(msg, ::list(head, tail))) {
710  return EC_fail;
711  };
712  }
713 
714  msg->ref();
715  try {
716  (iface)->msgq_enqueue(msg);
717  // return the msgID as 4th argument
718  EC_arg(4).unify((int)(msg->id()));
719  msg->unref();
720  } catch (Exception &e) {
721  msg->unref();
722  e.print_trace();
723  return EC_fail;
724  }
725 
726  } catch (Exception &e) {
727  fprintf(stderr, "p_bb_send_message() failed: %s\n", e.what_no_backtrace());
728  return EC_fail;
729  }
730  } else {
731  fprintf(stderr, "p_bb_send_message(): no interface with name %s\n", uid);
732  return EC_fail;
733  }
734 
735  return EC_succeed;
736 }
737 
738 int
739 p_bb_recv_messages()
740 {
741  char *uid;
742 
743  if (EC_succeed != EC_arg(1).is_string(&uid)) {
744  fprintf(stderr, "p_bb_recv_messages(): no interface uid given\n");
745  return EC_fail;
746  }
747 
748  std::map<std::string, Interface *> &interfaces = EclExternalBlackBoard::instance()->interfaces();
749 
750  if (interfaces.find(uid) != interfaces.end()) {
751  Interface *iface = interfaces[uid];
752 
753  if (!iface->is_writer()) {
754  fprintf(stderr, "p_bb_recv_messages(): interface with uid %s is not a writer\n", uid);
755  return EC_fail;
756  }
757 
758  EC_word msg_list = nil();
759 
760  while (!iface->msgq_empty()) {
761  Message *msg = iface->msgq_first();
762 
763  // construct list of key-value pairs: [[field1, val1], [field2, val2], ...]
764  EC_word args = nil();
765  for (InterfaceFieldIterator fit = msg->fields(); fit != msg->fields_end(); ++fit) {
766  EC_word value;
767 
768  switch (fit.get_type()) {
769  case IFT_BOOL:
770  if (fit.get_bool()) {
771  value = EC_atom((char *)"true");
772  } else {
773  value = EC_atom((char *)"false");
774  }
775 
776  break;
777 
778  case IFT_INT8: value = EC_word((long)fit.get_int8()); break;
779 
780  case IFT_UINT8: value = EC_word((long)fit.get_uint8()); break;
781 
782  case IFT_INT16: value = EC_word((long)fit.get_int16()); break;
783 
784  case IFT_UINT16: value = EC_word((long)fit.get_uint16()); break;
785 
786  case IFT_INT32: value = EC_word((long)fit.get_int32()); break;
787 
788  case IFT_UINT32: value = EC_word((long)fit.get_uint32()); break;
789 
790  case IFT_INT64: value = EC_word((long)fit.get_int64()); break;
791 
792  case IFT_UINT64: value = EC_word((long)fit.get_uint64()); break;
793 
794  case IFT_FLOAT: value = EC_word((double)fit.get_float()); break;
795 
796  case IFT_STRING: value = EC_word(fit.get_string()); break;
797 
798  case IFT_BYTE:
799  case IFT_ENUM: fprintf(stderr, "p_bb_recv_messages(): NOT YET IMPLEMENTED\n"); break;
800 
801  default: fprintf(stderr, "p_bb_recv_messages(): unknown field type\n");
802  }
803 
804  EC_word field = ::list(EC_word(fit.get_name()), ::list(value, nil()));
805  args = ::list(field, args);
806  }
807 
808  // construct list of messages: [[MsgType, [[Key1, Val1], ...]], ... ]
809  msg_list = ::list(::list(EC_word(msg->type()), ::list(args, nil())), msg_list);
810 
811  iface->msgq_pop();
812  }
813 
814  if (EC_succeed != EC_arg(2).unify(msg_list)) {
815  fprintf(stderr, "p_bb_recv_messages(): could not bind return value\n");
816  return EC_fail;
817  }
818 
819  } else {
820  fprintf(stderr, "p_bb_recv_messages(): no interface with id %s found\n", uid);
821  return EC_fail;
822  }
823 
824  return EC_succeed;
825 }
826 
827 int
828 p_bb_observe_pattern()
829 {
830  char *type_pattern, *id_pattern;
831  if (EC_succeed != EC_arg(1).is_string(&type_pattern)) {
833  "%s: First argument must be a string.",
834  __func__);
835  return EC_fail;
836  }
837  if (EC_succeed != EC_arg(2).is_string(&id_pattern)) {
839  "%s: Second argument must be a string.",
840  __func__);
841  return EC_fail;
842  }
843 
844  BlackboardListenerThread::instance()->observe_pattern(type_pattern, id_pattern);
845  return EC_succeed;
846 }
847 
848 int
849 p_bb_listen_for_change()
850 {
851  char *type, *id;
852  if (EC_succeed != EC_arg(1).is_string(&type)) {
854  "%s: First argument must be a string.",
855  __func__);
856  return EC_fail;
857  }
858  if (EC_succeed != EC_arg(2).is_string(&id)) {
860  "%s: Second argument must be a string.",
861  __func__);
862  return EC_fail;
863  }
864 
865  std::map<std::string, Interface *> &interfaces = EclExternalBlackBoard::instance()->interfaces();
866 
867  std::string uid = std::string(type) + "::" + id;
868  std::map<std::string, Interface *>::iterator iface_it = interfaces.find(uid);
869 
870  if (iface_it == interfaces.end()) {
872  "%s: Interface %s has not been opened.",
873  __func__,
874  uid.c_str());
875  return EC_fail;
876  }
877 
879  return EC_succeed;
880 }
881 
882 bool
883 process_message_args(Message *msg, EC_word arg_list)
884 {
885  EC_word head;
886  EC_word tail;
887 
888  for (; EC_succeed == arg_list.is_list(head, tail); arg_list = tail) {
889  // [field, value]
890  EC_word field;
891  EC_word value;
892  EC_word t1;
893  EC_word t2;
894 
895  if (EC_succeed != head.is_list(field, t1) || EC_succeed != t1.is_list(value, t2)) {
896  fprintf(stderr, "p_bb_send_messge(): could not parse argument list\n");
897  return false;
898  }
899 
900  char *field_name;
901  if (EC_succeed != field.is_string(&field_name)) {
902  fprintf(stderr, "p_bb_send_message(): malformed argument list\n");
903  return false;
904  }
905 
907  for (fit = msg->fields(); fit != msg->fields_end(); ++fit) {
908  if (0 == strcmp(fit.get_name(), field_name)) {
909  switch (fit.get_type()) {
910  case IFT_BOOL: {
911  EC_atom val;
912  if (EC_succeed != value.is_atom(&val)) {
913  fprintf(stderr, "p_bb_send_message(): no value_given (bool)\n");
914  return false;
915  }
916 
917  if (0 == strcmp("true", val.name())) {
918  fit.set_bool(true);
919  } else if (0 == strcmp("false", val.name())) {
920  fit.set_bool(false);
921  } else {
922  fprintf(stderr, "p_bb_send_message(): boolean value neither true nor false\n");
923  return false;
924  }
925  }
926 
927  break;
928 
929  case IFT_INT8: {
930  long val;
931  if (EC_succeed != value.is_long(&val)) {
932  fprintf(stderr, "p_bb_send_message(): no value given (int8)\n");
933  return false;
934  }
935 
936  fit.set_int8((int8_t)val);
937  }
938 
939  break;
940 
941  case IFT_UINT8: {
942  long val;
943  if (EC_succeed != value.is_long(&val)) {
944  fprintf(stderr, "p_bb_send_message(): no value given (uint8)\n");
945  return false;
946  }
947 
948  fit.set_uint8((uint8_t)val);
949  }
950 
951  break;
952 
953  case IFT_INT16: {
954  long val;
955  if (EC_succeed != value.is_long(&val)) {
956  fprintf(stderr, "p_bb_send_message(): no value given (int16)\n");
957  return false;
958  }
959 
960  fit.set_int16((int16_t)val);
961  }
962 
963  break;
964 
965  case IFT_UINT16: {
966  long val;
967  if (EC_succeed != value.is_long(&val)) {
968  fprintf(stderr, "p_bb_send_message(): no value given (uint16)\n");
969  return false;
970  }
971 
972  fit.set_uint16((uint16_t)val);
973  }
974 
975  break;
976 
977  case IFT_INT32: {
978  long val;
979  if (EC_succeed != value.is_long(&val)) {
980  fprintf(stderr, "p_bb_send_message(): no value given (int32)\n");
981  return false;
982  }
983 
984  fit.set_int32((int32_t)val);
985  }
986 
987  break;
988 
989  case IFT_UINT32: {
990  long val;
991  if (EC_succeed != value.is_long(&val)) {
992  fprintf(stderr, "p_bb_send_message(): no value given (uint32)\n");
993  return false;
994  }
995 
996  fit.set_uint32((uint32_t)val);
997  }
998 
999  break;
1000 
1001  case IFT_INT64: {
1002  long val;
1003  if (EC_succeed != value.is_long(&val)) {
1004  fprintf(stderr, "p_bb_send_message(): no value given (int64)\n");
1005  return false;
1006  }
1007 
1008  fit.set_int64((int64_t)val);
1009  }
1010 
1011  break;
1012 
1013  case IFT_UINT64: {
1014  long val;
1015  if (EC_succeed != value.is_long(&val)) {
1016  fprintf(stderr, "p_bb_send_message(): no value given (uint64)\n");
1017  return false;
1018  }
1019 
1020  fit.set_uint64((uint64_t)val);
1021  }
1022 
1023  break;
1024 
1025  case IFT_FLOAT: {
1026  double val;
1027  if (EC_succeed != value.is_double(&val)) {
1028  fprintf(stderr, "p_bb_send_message(): no value given (float)\n");
1029  return false;
1030  }
1031 
1032  fit.set_float((float)val);
1033  }
1034 
1035  break;
1036 
1037  case IFT_STRING: {
1038  char *val;
1039  if (EC_succeed != value.is_string(&val)) {
1040  fprintf(stderr, "p_bb_send_message(): no value given (string)\n");
1041  return false;
1042  }
1043 
1044  fit.set_string(val);
1045  }
1046 
1047  break;
1048 
1049  case IFT_BYTE:
1050  case IFT_ENUM: fprintf(stderr, "p_bb_send_message(): NOT YET IMPLEMENTET\n"); break;
1051 
1052  default: break;
1053  }
1054 
1055  break;
1056  }
1057  }
1058 
1059  if (fit == msg->fields_end()) {
1060  fprintf(stderr, "p_bb_send_message(): message has no field with name %s\n", field_name);
1061  return false;
1062  }
1063  }
1064 
1065  return true;
1066 }
static BlackboardListenerThread * instance()
Get the singleton instance of this thread.
void listen_for_change(Interface *interface) noexcept
Register.
void observe_pattern(const char *type_pattern, const char *id_pattern) noexcept
Trigger events if an interface matching the pattern is created or destroyed.
The BlackBoard abstract class.
Definition: blackboard.h:46
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.
Wrapper class for using the blackboard in the implementation of the external predicates.
Definition: blackboard.h:40
static Logger * logger()
Definition: blackboard.h:62
std::map< std::string, Interface * > & interfaces()
Obtain the list of opened interfaces.
Definition: blackboard.cpp:101
static void create_initial_object(BlackBoard *bb, Logger *logger)
Creates the initial EclExternalBlackBoard object.
Definition: blackboard.cpp:64
~EclExternalBlackBoard()
Destructor.
Definition: blackboard.cpp:55
static const char * name()
Definition: blackboard.h:71
static BlackBoard * blackboard_instance()
Access the BlackBoard instance.
Definition: blackboard.cpp:92
static void cleanup_instance()
Delete the current EclExternalBlackBoard instance and set it to NULL.
Definition: blackboard.cpp:71
static EclExternalBlackBoard * instance()
Get the EclExternalBlackBoard instance.
Definition: blackboard.cpp:83
Base class for exceptions in Fawkes.
Definition: exception.h:36
void print_trace() noexcept
Prints trace to stderr.
Definition: exception.cpp:601
virtual const char * what_no_backtrace() const noexcept
Get primary string (does not implicitly print the back trace).
Definition: exception.cpp:663
Interface field iterator.
float get_float(unsigned int index=0) const
Get value of current field as float.
int16_t get_int16(unsigned int index=0) const
Get value of current field as integer.
void set_int64(int64_t i, unsigned int index=0)
Set value of current field as integer.
int8_t get_int8(unsigned int index=0) const
Get value of current field as integer.
float * get_floats() const
Get value of current field as float array.
int32_t get_int32(unsigned int index=0) const
Get value of current field as integer.
uint8_t * get_bytes() const
Get value of current field as byte array.
void set_string(const char *s)
Set value of current field as string.
size_t get_length() const
Get length of current field.
int64_t get_int64(unsigned int index=0) const
Get value of current field as integer.
uint64_t get_uint64(unsigned int index=0) const
Get value of current field as unsigned integer.
void set_int16(int16_t i, unsigned int index=0)
Set value of current field as integer.
uint16_t get_uint16(unsigned int index=0) const
Get value of current field as unsigned integer.
double get_double(unsigned int index=0) const
Get value of current field as double.
uint32_t get_uint32(unsigned int index=0) const
Get value of current field as unsigned integer.
void set_uint64(uint64_t i, unsigned int index=0)
Set value of current field as unsigned integer.
interface_fieldtype_t get_type() const
Get type of current field.
const char * get_name() const
Get name of current field.
void set_float(float f, unsigned int index=0)
Set value of current field as float.
void set_uint16(uint16_t i, unsigned int index=0)
Set value of current field as unsigned integer.
void set_int32(int32_t i, unsigned int index=0)
Set value of current field as integer.
const char * get_string() const
Get value of current field as string.
uint8_t get_byte(unsigned int index=0) const
Get value of current field as byte.
uint8_t get_uint8(unsigned int index=0) const
Get value of current field as unsigned integer.
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.
double * get_doubles() const
Get value of current field as double array.
void set_bool(bool b, unsigned int index=0)
Set value of current field as bool.
void set_int8(int8_t i, unsigned int index=0)
Set value of current field as integer.
void set_uint8(uint8_t i, unsigned int index=0)
Set value of current field as unsigned integer.
void set_uint32(uint32_t i, unsigned int index=0)
Set value of current field as unsigned integer.
const char * get_typename() const
Get type of current field as string.
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:80
void msgq_pop()
Erase first message from queue.
Definition: interface.cpp:1215
Message * msgq_first()
Get the first message from the message queue.
Definition: interface.cpp:1200
InterfaceFieldIterator fields_end()
Invalid iterator.
Definition: interface.cpp:1240
virtual Message * create_message(const char *type) const =0
Create message based on type name.
bool is_writer() const
Check if this is a writing instance.
Definition: interface.cpp:445
InterfaceFieldIterator fields()
Get iterator over all fields of this interface instance.
Definition: interface.cpp:1231
bool msgq_empty()
Check if queue is empty.
Definition: interface.cpp:1062
const char * uid() const
Get unique identifier of interface.
Definition: interface.cpp:686
Interface for logging.
Definition: logger.h:42
virtual void log_error(const char *component, const char *format,...)=0
Log error message.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
Definition: message.h:44
InterfaceFieldIterator fields()
Get iterator over all fields of this interface instance.
Definition: message.cpp:390
const char * type() const
Get message type.
Definition: message.cpp:381
InterfaceFieldIterator fields_end()
Invalid iterator.
Definition: message.cpp:399
unsigned int id() const
Get message ID.
Definition: message.cpp:181
void unref()
Decrement reference count and conditionally delete this instance.
Definition: refcount.cpp:95
void ref()
Increment reference count.
Definition: refcount.cpp:67
Fawkes library namespace.
@ IFT_INT8
8 bit integer field
Definition: types.h:38
@ IFT_UINT32
32 bit unsigned integer field
Definition: types.h:43
@ IFT_FLOAT
float field
Definition: types.h:46
@ IFT_BYTE
byte field, alias for uint8
Definition: types.h:49
@ IFT_UINT64
64 bit unsigned integer field
Definition: types.h:45
@ IFT_UINT16
16 bit unsigned integer field
Definition: types.h:41
@ IFT_INT32
32 bit integer field
Definition: types.h:42
@ IFT_INT64
64 bit integer field
Definition: types.h:44
@ IFT_DOUBLE
double field
Definition: types.h:47
@ IFT_INT16
16 bit integer field
Definition: types.h:40
@ IFT_STRING
string field
Definition: types.h:48
@ IFT_BOOL
boolean field
Definition: types.h:37
@ IFT_ENUM
field with interface specific enum type
Definition: types.h:50
@ IFT_UINT8
8 bit unsigned integer field
Definition: types.h:39