7.1.3. Binary: Blob#

Last but not least we want to show how you can send binary data with eCAL. When you read through the previous chapters, you will see that you are already familiar with most of the code.

The biggest difference is that you basically can send any kind of data. But be aware that you also need to handle the binary interpretation across multiple platforms, which is handled before simply through a serialization protocol.

7.1.3.1. Blob Publisher#

The main differences to serialization publishers are:
  • you don’t need to include any serialization header file in addition to the convenience header

  • you send a binary buffer with a buffer size

 1// Include the eCAL convenience header
 2#include <ecal/ecal.h>
 3
 4#include <algorithm>
 5#include <iostream>
 6#include <chrono>
 7#include <random>
 8
 9/*
10  Some helper function to generate binary data into a buffer.
11  Clears the vector, resizes it to a specified size and fills it with random printable ascii characters.
12*/
13void fillBinaryBuffer(std::vector<unsigned char>& buffer) { 
14  constexpr unsigned int buffer_size = 16;
15
16  static std::random_device random_device;
17  static std::mt19937 generator(random_device());
18  // Useful random characters are in the range [32, 126]
19  static std::uniform_int_distribution<> printable_ascii_char(32, 126);
20  
21  buffer.clear();
22  buffer.resize(buffer_size);
23
24  for (unsigned int i = 0; i < buffer_size; ++i) {
25    buffer[i] = static_cast<char>(printable_ascii_char(generator));
26  }
27}
28
29int main()
30{
31  std::cout << "-------------------" << "\n";
32  std::cout << " C++: BLOB SENDER"   << "\n";
33  std::cout << "-------------------" << "\n";
34
35  /*
36    Initialize eCAL. You always have to initialize eCAL before using its API.
37    The name of our eCAL Process will be "blob send". 
38    This name will be visible in the eCAL Monitor, once the process is running.
39  */
40  eCAL::Initialize("blob send");
41
42  /*
43    Print some eCAL version information.
44  */
45  std::cout << "eCAL " << eCAL::GetVersionString() << " (" << eCAL::GetVersionDateString() << ")" << "\n";
46
47  /*
48    Set the state for the program.
49    You can vary between different states like healthy, warning, critical ...
50    This can be used to communicate the application state to applications like eCAL Monitor/Sys.
51  */
52  eCAL::Process::SetState(eCAL::Process::eSeverity::healthy, eCAL::Process::eSeverityLevel::level1, "I feel good!");
53
54  /*
55    Now we create a new publisher that will publish the topic "blob".
56  */
57  eCAL::CPublisher pub("blob");
58
59  /*
60    Construct a message. As we are sending binary data, we just create a buffer of unsigned characters.
61  */
62  std::vector<unsigned char> binary_buffer;
63
64  /*
65    Creating an infinite publish-loop.
66    eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL_Ok() will return false.
67  */
68  while (eCAL::Ok())
69  {
70    /*
71      Fill the buffer with the character that is defined by the counter variable.
72    */
73    fillBinaryBuffer(binary_buffer);
74
75    /*
76      Send the message. The message is sent to all subscribers that are currently connected to the topic "blob".
77      For binary data you need to set a buffer pointer and the size of the buffer.
78    */
79    if (pub.Send(binary_buffer.data(), binary_buffer.size()))
80      std::cout << "Sent binary data in C++: " << std::string(binary_buffer.begin(), binary_buffer.end()) << "\n";
81    else
82      std::cout << "Sending binary data in C++ failed!" << "\n";
83
84    /*
85      Sleep for 500ms to send in a frequency of 2 hz.
86    */
87    eCAL::Process::SleepMS(500);
88  }
89
90  /*
91    Finalize eCAL. This will stop all eCAL processes and free all resources.
92    You should always finalize eCAL when you are done using it.
93  */
94  eCAL::Finalize();
95
96  return(0);
97}

7.1.3.2. Blob Publisher Files#


├─  C++
│  └─  blob_send.cpp
│
├─  C
│  └─  blob_send.c
│
├─  C#
│  └─  blob_send.cs
│
└─  Python
   └─  blob_send.py

7.1.3.3. Blob Subscriber#

For the subscriber the same changes apply as for the publisher. In addition you need to take care of the blob handling yourself.

 1// Include the eCAL convenience header
 2#include <ecal/ecal.h>
 3
 4#include <iostream>
 5#include <sstream>
 6#include <chrono>
 7#include <thread>
 8#include <string>
 9
10/*
11  Here we create the subscriber callback function that is called everytime,
12  when a new message arrived from a publisher.
13*/
14void OnReceive(const eCAL::STopicId& topic_id_, const eCAL::SDataTypeInformation& /*data_type_info_*/, const eCAL::SReceiveCallbackData& data_)
15{
16  if (data_.buffer_size < 1) return;
17  const char* char_buffer = static_cast<const char*>(data_.buffer);
18  
19  std::cout << "------------------------------------------------------------"                  << "\n";
20  std::cout << " Received binary buffer from topic \"" << topic_id_.topic_name << "\" in C++ " << "\n";
21  std::cout << "------------------------------------------------------------"                  << "\n";
22  std::cout << " Size    : " << data_.buffer_size                                              << "\n";
23  std::cout << " Time    : " << data_.send_timestamp                                           << "\n";
24  std::cout << " Clock   : " << data_.send_clock                                               << "\n";
25  std::cout << " Content : " << std::string(char_buffer, data_.buffer_size)                    << "\n";
26  std::cout << "\n";
27}
28
29int main()
30{
31  std::cout << "---------------------" << "\n";
32  std::cout << " C++: BLOB RECEIVER"   << "\n";
33  std::cout << "---------------------" << "\n";
34
35  /*
36    Initialize eCAL. You always have to initialize eCAL before using its API.
37    The name of our eCAL Process will be "blob receive". 
38    This name will be visible in the eCAL Monitor, once the process is running.
39  */
40  eCAL::Initialize("blob receive");
41
42  /*
43    Print some eCAL version information.
44  */
45  std::cout << "eCAL " << eCAL::GetVersionString() << " (" << eCAL::GetVersionDateString() << ")" << "\n";
46
47  /*
48    Set the state for the program.
49    You can vary between different states like healthy, warning, critical ...
50    This can be used to communicate the application state to applications like eCAL Monitor/Sys.
51  */
52  eCAL::Process::SetState(eCAL::Process::eSeverity::healthy, eCAL::Process::eSeverityLevel::level1, "I feel good!");
53
54  /*
55    Creating the eCAL Subscriber. An eCAL Process can create multiple subscribers (and publishers).
56    The topic we are going to receive is called "blob".
57  */
58  eCAL::CSubscriber subscriber("blob");
59
60  /*
61    Register a receive callback. The callback will be called whenever a new message is received.
62  */
63  subscriber.SetReceiveCallback(OnReceive);
64
65  /*
66    Creating an infinite loop.
67    eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL::Ok() will return false.
68  */
69  while (eCAL::Ok())
70  {
71    /*
72      Sleep for 500ms to avoid busy waiting.
73    */
74    std::this_thread::sleep_for(std::chrono::milliseconds(500));
75  }
76
77  /*
78    Finalize eCAL. This will stop all eCAL processes and free all resources.
79    You should always finalize eCAL before exiting your application.
80  */
81  eCAL::Finalize();
82
83  return(0);
84}

7.1.3.4. Blob Subscriber Files#


├─  C++
│  └─  blob_receive.cpp
│
├─  C
│  └─  blob_receive.c
│
├─  C#
│  └─  blob_receive.cs
│
└─  Python
   └─  blob_receive.py