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
33namespace 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
40BlackBoard * EclExternalBlackBoard::m_blackboard = NULL;
41EclExternalBlackBoard *EclExternalBlackBoard::m_instance = NULL;
42
43/** Constructor. */
44EclExternalBlackBoard::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 */
63void
65{
66 m_instance = new EclExternalBlackBoard(bb, logger);
67}
68
69/** Delete the current EclExternalBlackBoard instance and set it to NULL */
70void
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 */
93{
94 return m_blackboard;
95}
96
97/** Obtain the list of opened interfaces.
98 * @return list of opened interfaces
99 */
100std::map<std::string, Interface *> &
102{
103 return m_interfaces;
104}
105
106} // namespace fawkes
107
108using namespace fawkes;
109
110bool process_message_args(Message *msg, EC_word arg_list);
111
112int
113p_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 =
143 EclExternalBlackBoard::instance()->blackboard_instance()->open_for_writing(interface_type,
144 interface_id);
145 } else {
146 iface =
147 EclExternalBlackBoard::instance()->blackboard_instance()->open_for_reading(interface_type,
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
165int
166p_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()) {
178 EclExternalBlackBoard::instance()->blackboard_instance()->close(interfaces[uid]);
179 EclExternalBlackBoard::instance()->interfaces().erase(uid);
180 }
181
182 return EC_succeed;
183}
184
185int
186p_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
204int
205p_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
227int
228p_bb_read_interfaces()
229{
230 for (std::map<std::string, Interface *>::iterator it =
231 EclExternalBlackBoard::instance()->interfaces().begin();
232 it != EclExternalBlackBoard::instance()->interfaces().end();
233 ++it) {
234 it->second->read();
235 }
236
237 return EC_succeed;
238}
239
240int
241p_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
261int
262p_bb_write_interfaces()
263{
264 for (std::map<std::string, Interface *>::iterator it =
265 EclExternalBlackBoard::instance()->interfaces().begin();
266 it != EclExternalBlackBoard::instance()->interfaces().end();
267 ++it) {
268 if (it->second->is_writer()) {
269 it->second->write();
270 }
271 }
272
273 return EC_succeed;
274}
275
276int
277p_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
301int
302p_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
320int
321p_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
507int
508p_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
677int
678p_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
738int
739p_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
827int
828p_bb_observe_pattern()
829{
830 char *type_pattern, *id_pattern;
831 if (EC_succeed != EC_arg(1).is_string(&type_pattern)) {
832 EclExternalBlackBoard::logger()->log_error(EclExternalBlackBoard::name(),
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)) {
838 EclExternalBlackBoard::logger()->log_error(EclExternalBlackBoard::name(),
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
848int
849p_bb_listen_for_change()
850{
851 char *type, *id;
852 if (EC_succeed != EC_arg(1).is_string(&type)) {
853 EclExternalBlackBoard::logger()->log_error(EclExternalBlackBoard::name(),
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)) {
859 EclExternalBlackBoard::logger()->log_error(EclExternalBlackBoard::name(),
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()) {
871 EclExternalBlackBoard::logger()->log_error(EclExternalBlackBoard::name(),
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
882bool
883process_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
Wrapper class for using the blackboard in the implementation of the external predicates.
Definition: blackboard.h:40
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 Logger * logger()
Definition: blackboard.h:62
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
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