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}
1// Include the basic eCAL header
2#include <ecal_c/ecal.h>
3
4#include <stdio.h>
5#include <string.h>
6#include <stdlib.h>
7#include <time.h>
8
9#define BUFFER_SIZE 16
10
11/*
12 Some helper function to generate binary data into a binary_buffer.
13 Clears the vector, resizes it to a specified size and fills it with random ascii characters.
14*/
15void fillBinaryBuffer(unsigned char* binary_buffer, size_t buffer_size)
16{
17 unsigned int milliseconds = (unsigned int)(clock());
18 srand(milliseconds); // Seed with milliseconds
19
20 for (size_t i = 0; i < buffer_size; ++i)
21 {
22 binary_buffer[i] = (unsigned char)(rand() % 95 + 32); // ASCII range 32-126
23 }
24
25}
26
27int main()
28{
29 printf("----------------\n");
30 printf(" C: BLOB SENDER\n");
31 printf("----------------\n");
32
33 /*
34 We create the objects we want to work with.
35 In this case we need a publisher handle.
36 Additionally we need a char binary_buffer to hold the content we want to send.
37 */
38 eCAL_Publisher* publisher;
39 unsigned char binary_buffer[BUFFER_SIZE];
40
41 /*
42 Initialize eCAL. You always have to initialize eCAL before using its API.
43 The name of our eCAL Process will be "blob send c".
44 This name will be visible in the eCAL Monitor, once the process is running.
45 */
46 eCAL_Initialize("blob send c", NULL, NULL);
47
48 /*
49 Print some eCAL version information.
50 */
51 printf("eCAL %s (%s)\n", eCAL_GetVersionString(), eCAL_GetVersionDateString());
52
53 /*
54 Set the state for the program.
55 You can vary between different states like healthy, warning, critical ...
56 This can be used to communicate the application state to applications like eCAL Monitor/Sys.
57 */
58 eCAL_Process_SetState(eCAL_Process_eSeverity_healthy, eCAL_Process_eSeverityLevel_level1, "I feel good!");
59
60 /*
61 Now we create a new publisher that will publish the topic "blob".
62 Furthermore we set the data type information of the publisher.
63 The two additional parameters that could be set (eCAL_PubEventCallbackT and eCAL_Publisher_Configuration)
64 are set to NULL, because for this example we are fine with the default settings.
65 */
66 publisher = eCAL_Publisher_New("blob", NULL, NULL, NULL);
67
68 /*
69 Creating an infinite publish-loop.
70 eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL_Ok() will return false.
71 */
72 while(eCAL_Ok())
73 {
74 /*
75 Build the blob you want to send. You can add any binary data here, we fill the message with the loop count.
76 */
77 fillBinaryBuffer(binary_buffer, BUFFER_SIZE);
78
79 /*
80 Send the content to other eCAL Processes that have subscribed to the topic "blob".
81 The message is sent as binary, so we use the size of the message as the size of the message to send.
82 */
83 if(!eCAL_Publisher_Send(publisher, binary_buffer, BUFFER_SIZE, NULL))
84 printf("Sent binary data in C: \"%.*s\"\n", BUFFER_SIZE, binary_buffer);
85 else
86 printf("Sending binary data in C failed!\n");
87
88 /*
89 Sleep for 500 ms so we send with a frequency of 2 Hz.
90 */
91 eCAL_Process_SleepMS(500);
92 }
93
94 /*
95 Now we delete the publisher handle. This is important to free resources.
96 All objects that are created with eCAL_xxx_New() have to be deleted with eCAL_xxx_Delete().
97 */
98 eCAL_Publisher_Delete(publisher);
99
100
101 /*
102 Deinitialize eCAL.
103 You should always do that before your application exits.
104 */
105 eCAL_Finalize();
106
107 return(0);
108}
1using System;
2using System.Text;
3using System.Threading;
4using Eclipse.eCAL.Core;
5
6public class BlobSend
7{
8 /*
9 Some helper function to generate binary data into a buffer.
10 Clears the vector, resizes it to a specified size and fills it with random ascii characters.
11 */
12 static void GenerateBinaryMessage(byte[] buffer)
13 {
14 Random rand = new Random();
15 for (int i = 0; i < buffer.Length; ++i)
16 {
17 buffer[i] = (byte)(rand.Next(32, 127)); // ASCII range 32-126
18 }
19 }
20
21 public static void Main()
22 {
23 Console.WriteLine("-----------------");
24 Console.WriteLine(" C#: BLOB SENDER");
25 Console.WriteLine("-----------------");
26
27 /*
28 Initialize eCAL. You always have to initialize eCAL before using its API.
29 The name of our eCAL Process will be "blob send c#".
30 This name will be visible in the eCAL Monitor, once the process is running.
31 */
32 Core.Initialize("blob send c#");
33
34 /*
35 Print version info.
36 */
37 Console.WriteLine(String.Format("eCAL {0} ({1})\n", Core.GetVersionString(), Core.GetVersionDateString()));
38
39 /*
40 Set the state for the program.
41 You can vary between different states like healthy, warning, critical ...
42 This can be used to communicate the application state to applications like eCAL Monitor/Sys.
43 */
44 Process.SetState(eProcessSeverity.Healthy, eProcessSeverityLevel.Level1, "I feel good!");
45
46 /*
47 Now we create a new publisher that will publish the topic "blob".
48 */
49 Publisher publisher = new Publisher("blob");
50
51 const int buffer_size = 16;
52 byte[] buffer = new byte[buffer_size];
53
54 /*
55 Creating an infinite publish-loop.
56 eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL_Ok() will return false.
57 */
58 while (Core.Ok())
59 {
60 /*
61 Construct a message. The message is a string that will be sent to the subscribers.
62 */
63 GenerateBinaryMessage(buffer);
64
65 /*
66 Send the message. The message is sent to all subscribers that are currently connected to the topic "blob".
67 */
68 if(publisher.Send(buffer, buffer_size))
69 Console.WriteLine(String.Format("Sent binary data in C#: {0}", System.Text.Encoding.ASCII.GetString(buffer, 0, buffer_size)));
70 else
71 Console.WriteLine("Sending binary data in C# failed!");
72
73 /*
74 Sleep for 500ms to send in a frequency of 2 hz.
75 */
76 Thread.Sleep(500);
77 }
78
79 /*
80 Cleanup. Dispose the publisher to free resources.
81 */
82 publisher.Dispose();
83
84 /*
85 Terminate eCAL. This will stop all eCAL processes and free all resources.
86 You should always terminate eCAL when you are done using it.
87 */
88 Core.Terminate();
89 }
90}
1import sys
2import time
3import random
4
5# Import the eCAL core API
6import ecal.core.core as ecal_core
7# Import the eCAL binary publisher API
8from ecal.core.publisher import BinaryPublisher
9
10
11def generate_binary_message(buffer_size=16):
12 random.seed(time.time())
13 return ''.join(chr(random.randint(32, 126)) for _ in range(buffer_size))
14
15
16def main():
17 print("---------------------")
18 print(" Python: BLOB SENDER")
19 print("---------------------")
20
21 # Initialize eCAL. You always have to initialize eCAL before using it.
22 # The name of our eCAL Process will be "blob send python".
23 # This name will be visible in the eCAL Monitor, once the process is running.
24 ecal_core.initialize("blob send python")
25
26 # Print used eCAL version and date
27 print("eCAL {} ({})\n".format(ecal_core.getversion(), ecal_core.getdate()))
28
29 # Set the state for the program.
30 # You can vary between different states like healthy, warning, critical ...
31 # This can be used to communicate the application state to applications like eCAL Monitor/Sys.
32 ecal_core.set_process_state(1, 1, "I feel good!")
33
34 # Creating the eCAL Publisher. An eCAL Process can create multiple publishers (and subscribers).
35 # The topic we are going to publish is called "blob".
36 pub = BinaryPublisher("blob")
37
38 loop_count = 0
39 # Creating an inifite publish-loop.
40 # eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL::Ok() will return false.
41 while ecal_core.ok():
42 # Generate a random message of 16 bytes
43 msg = generate_binary_message(16)
44
45 # Send the content to other eCAL Processes that have subscribed to the topic "blob".
46 pub.send(msg)
47 print("Sent: ", msg)
48
49 loop_count += 1
50
51 # Sleep for 500 ms so we send with a frequency of 2 Hz.
52 time.sleep(0.5)
53
54 # Finalize eCAL.
55 # You should always do that before your application exits.
56 ecal_core.finalize()
57
58if __name__ == "__main__":
59 main()
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}
1// Include the basic eCAL header
2#include <ecal_c/ecal.h>
3
4#include <string.h> //memset()
5#include <stdio.h> //printf()
6
7
8/*
9 Here we create the receive callback function.
10 The function will be called whenever a new message is received.
11*/
12void OnReceive(const struct eCAL_STopicId* topic_id_, const struct eCAL_SDataTypeInformation* data_type_information_, const struct eCAL_SReceiveCallbackData* callback_data_, void* user_argument_)
13{
14 /*
15 These are unused arguments for this example.
16 You can use the data type information to check the data type of the received message.
17 The user argument can be used to work with user defined data when the callback is called.
18 */
19 (void)topic_id_;
20 (void)data_type_information_;
21 (void)user_argument_;
22
23 if (callback_data_->buffer_size < 1) return;
24 const char* char_buffer = (const char*)(callback_data_->buffer);
25
26 printf("----------------------------------------------\n");
27 printf(" Received binary buffer in C\n");
28 printf("----------------------------------------------\n");
29 printf(" Size : %zu\n", callback_data_->buffer_size);
30 printf(" Time : %lld\n", callback_data_->send_timestamp);
31 printf(" Clock : %lld\n", callback_data_->send_clock);
32 printf(" Content : %.*s\n", (int)callback_data_->buffer_size, char_buffer);
33 printf("\n");
34}
35
36int main()
37{
38 printf("------------------\n");
39 printf(" C: BLOB RECEIVER\n");
40 printf("------------------\n");
41
42 /*
43 We create the objects we want to work with.
44 In this case we need a subscriber handle.
45 */
46 eCAL_Subscriber *subscriber;
47
48 /*
49 Initialize eCAL. You always have to initialize eCAL before using its API.
50 The name of our eCAL Process will be "blob receive c".
51 This name will be visible in the eCAL Monitor, once the process is running.
52 */
53 eCAL_Initialize("blob receive c", NULL, NULL);
54
55 /*
56 Print some eCAL version information.
57 */
58 printf("eCAL %s (%s)\n", eCAL_GetVersionString(), eCAL_GetVersionDateString());
59
60 /*
61 Set the state for the program.
62 You can vary between different states like healthy, warning, critical ...
63 This can be used to communicate the application state to applications like eCAL Monitor/Sys.
64 */
65 eCAL_Process_SetState(eCAL_Process_eSeverity_healthy, eCAL_Process_eSeverityLevel_level1, "I feel good!");
66
67 /*
68 Now we create a new subscriber that will subscribe to the topic "blob".
69 The three additional parameters that could be set (eCAL_SDatatypeInformation, eCAL_SubEventCallbackT and eCAL_Subscriber_Configuration)
70 are set to NULL, because for this example we are fine with the default settings.
71 */
72 subscriber = eCAL_Subscriber_New("blob", NULL, NULL, NULL);
73
74 /*
75 In order to receive message, we need to register a receive callback.
76 The callback will be called whenever a new message is received.
77 */
78 eCAL_Subscriber_SetReceiveCallback(subscriber, OnReceive, NULL);
79
80 /*
81 Creating an infinite loop.
82 eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL_Ok() will return false.
83 */
84 while(eCAL_Ok())
85 {
86 /*
87 Sleep for 500ms to avoid busy waiting.
88 You can use eCAL_Process_SleepMS() to sleep in milliseconds.
89 */
90 eCAL_Process_SleepMS(500);
91 }
92
93 /*
94 Now we delete the subscriber handle. This is important to free resources.
95 All objects that are created with eCAL_xxx_New() have to be deleted with eCAL_xxx_Delete().
96 */
97 eCAL_Subscriber_Delete(subscriber);
98
99 /*
100 Deinitialize eCAL.
101 You should always do that before your application exits.
102 */
103 eCAL_Finalize();
104
105 return(0);
106}
1using System;
2using System.Text;
3// include ecal core namespace
4using Eclipse.eCAL.Core;
5
6public class BlobReceive
7{
8 public static void Main()
9 {
10 Console.WriteLine("-------------------");
11 Console.WriteLine(" C#: BLOB RECEIVER");
12 Console.WriteLine("-------------------");
13
14 /*
15 Initialize eCAL. You always have to initialize eCAL before using its API.
16 The name of our eCAL Process will be "blob receive c#".
17 This name will be visible in the eCAL Monitor, once the process is running.
18 */
19 Core.Initialize("blob receive c#");
20
21 /*
22 Print version info.
23 */
24 Console.WriteLine(String.Format("eCAL {0} ({1})\n", Core.GetVersionString(), Core.GetVersionDateString()));
25
26 /*
27 Set the state for the program.
28 You can vary between different states like healthy, warning, critical ...
29 This can be used to communicate the application state to applications like eCAL Monitor/Sys.
30 */
31 Process.SetState(eProcessSeverity.Healthy, eProcessSeverityLevel.Level1, "I feel good!");
32
33 /*
34 Creating the eCAL Subscriber. An eCAL Process can create multiple subscribers (and publishers).
35 The topic we are going to receive is called "blob".
36 */
37 Subscriber subscriber = new Subscriber("blob");
38
39 /*
40 Create and register a receive callback. The callback will be called whenever a new message is received.
41 */
42 subscriber.SetReceiveCallback((publisherId, dataTypeInfo, data) =>
43 {
44 Console.WriteLine("----------------------------------------------");
45 Console.WriteLine(" Received binary buffer in C# ");
46 Console.WriteLine("----------------------------------------------");
47 Console.WriteLine(" Size : " + Buffer.ByteLength(data.Buffer));
48 Console.WriteLine(" Time : " + data.SendTimestamp);
49 Console.WriteLine(" Clock : " + data.SendClock);
50 Console.WriteLine(" Content : " + System.Text.Encoding.ASCII.GetString(data.Buffer));
51 Console.WriteLine("");
52 });
53
54 /*
55 Creating an infinite loop.
56 eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL::Ok() will return false.
57 */
58 while (Core.Ok())
59 {
60 /*
61 Sleep for 500ms to avoid busy waiting.
62 */
63 System.Threading.Thread.Sleep(500);
64 }
65
66 /*
67 Cleanup. Dispose the subscriber to free resources.
68 */
69 subscriber.Dispose();
70
71 /*
72 Terminate eCAL. This will stop all eCAL processes and free all resources.
73 You should always terminate eCAL before exiting your application.
74 */
75 Core.Terminate();
76 }
77}
1import sys
2import time
3
4# Import the eCAL core API
5import ecal.core.core as ecal_core
6# Import the eCAL binary publisher API
7from ecal.core.subscriber import BinarySubscriber
8
9# Here we create the subscriber callback function that is called everytime,
10# when a new message arrived from a publisher.
11def callback(topic_name, msg, time):
12 print("----------------------------------------------")
13 print(" Received binary buffer in Python ")
14 print("----------------------------------------------")
15 print(" Size : ", msg.buffer_size)
16 print(" Time : ", msg.send_timestamp)
17 print(" Clock : ", msg.send_clock)
18 print(" Content : ", msg.buffer)
19 print("")
20
21def main():
22 print("-----------------------")
23 print(" Python: BLOB RECEIVER")
24 print("-----------------------")
25
26 # Initialize eCAL. You always have to initialize eCAL before using it.
27 # The name of our eCAL Process will be "blob receive python".
28 # This name will be visible in the eCAL Monitor, once the process is running.
29 ecal_core.initialize("blob receive python")
30
31 # Print used eCAL version and date
32 print("eCAL {} ({})\n".format(ecal_core.getversion(), ecal_core.getdate()))
33
34 # Set the state for the program.
35 # You can vary between different states like healthy, warning, critical ...
36 # This can be used to communicate the application state to applications like eCAL Monitor/Sys.
37 ecal_core.set_process_state(1, 1, "I feel good!")
38
39 # Creating the eCAL Subscriber. An eCAL Process can create multiple subscribers (and publishers).
40 # The topic we are going to receive is called "blob".
41 # The data type is "Pb.People.Person", generated from the protobuf definition.
42 sub = BinarySubscriber("blob")
43
44 # Register the callback with the subscriber so it can be called.
45 sub.set_callback(callback)
46
47 # Creating an inifite publish-loop.
48 # eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL::Ok() will return false.
49 while ecal_core.ok():
50 # Sleep for 500ms to avoid busy waiting.
51 # You can use eCAL::Process::SleepMS() to sleep in milliseconds.
52 time.sleep(0.5)
53
54 # Finalize eCAL.
55 # You should always do that before your application exits.
56 ecal_core.finalize()
57
58if __name__ == "__main__":
59 main()
60
7.1.3.4. Blob Subscriber Files#
├─ C++ │ └─blob_receive.cpp
│ ├─ C │ └─blob_receive.c
│ ├─ C# │ └─blob_receive.cs
│ └─ Python └─blob_receive.py