7.2.1. Binary: Mirror#
Under this section you will find a simple example of a client/server application using the eCAL ClientServer API. You should be already familiar with the base handling of eCAL from the Publisher/Subscriber samples, so this we will not be covered in detail any more.
7.2.1.1. Mirror Server#
A service server is an eCAL instance that is matched to service client instances by their name. It can offer multiple methods, which a connected service client can call. We will set up a simple server that provides two methods: “echo” and “mirror”.
The main process is:
Intialize eCAL
Create a Service Server
For each method, add meta information about that method (such as method name, and types of the request and response) and a callback function to be invoked, when a client calls that method
Keep the program running while the service is supposed to be executed
1#include <ecal/ecal.h>
2
3#include <algorithm>
4#include <iostream>
5#include <chrono>
6#include <thread>
7
8void printCallbackInformation(const eCAL::SServiceMethodInformation& method_info_, const std::string& request_, const std::string& response_)
9{
10 std::cout << "Method : '" << method_info_.method_name << "' called in C++" << "\n";
11 std::cout << "Request : " << request_ << "\n";
12 std::cout << "Response : " << response_ << "\n";
13 std::cout << "\n";
14}
15
16/*
17 We define the callback function that will be called when a client calls the service method "echo".
18 This callback will simply return the request as the response.
19*/
20int OnEchoCallback(const eCAL::SServiceMethodInformation& method_info_, const std::string& request_, std::string& response_)
21{
22 response_ = request_;
23
24 printCallbackInformation(method_info_, request_, response_);
25
26 // The return value here has no actual meaning. It's made available to the caller.
27 return 0;
28}
29
30/*
31 This callback will be called when a client calls the service method "reverse".
32 It will return the request in reverse order as the response.
33*/
34int OnReverseCallback(const eCAL::SServiceMethodInformation& method_info_, const std::string& request_, std::string& response_)
35{
36 response_.resize(request_.size());
37 std::copy(request_.rbegin(), request_.rend(), response_.begin());
38
39 printCallbackInformation(method_info_, request_, response_);
40
41 // The return value here has no actual meaning. It's made available to the caller.
42 return 0;
43}
44
45int main()
46{
47 std::cout << "--------------------" << "\n";
48 std::cout << " C++: MIRROR SERVER" << "\n";
49 std::cout << "--------------------" << "\n";
50
51 /*
52 As always: initialize the eCAL API and give your process a name.
53 */
54 eCAL::Initialize("mirror server");
55
56 std::cout << "eCAL " << eCAL::GetVersionString() << " (" << eCAL::GetVersionDateString() << ")" << "\n";
57 eCAL::Process::SetState(eCAL::Process::eSeverity::healthy, eCAL::Process::eSeverityLevel::level1, "I feel good!");
58
59 /*
60 Now we create the mirror server and give it the name "mirror".
61 */
62 eCAL::CServiceServer mirror_server("mirror");
63
64 /*
65 The server will have two methods: "echo" and "reverse".
66 To set a callback, we need to set a ServiceMethodInformation struct as well as the callback function.
67 We simplify the struct creation of ServiceMethodInformationStruct and the other two
68 fields can be left empty for our example.
69 */
70 mirror_server.SetMethodCallback({ "echo", {}, {} }, OnEchoCallback);
71 mirror_server.SetMethodCallback({ "reverse", {}, {} }, OnReverseCallback);
72
73 /*
74 Now we will go in an infinite loop, to wait for incoming service calls that will be handled with the callbacks.
75 */
76 while(eCAL::Ok())
77 {
78 std::this_thread::sleep_for(std::chrono::milliseconds(500));
79 }
80
81 /*
82 After we are done, as always, finalize the eCAL API.
83 */
84 eCAL::Finalize();
85
86 return(0);
87}
1#include <ecal_c/ecal.h>
2
3#include <stdio.h> //printf()
4#include <string.h> //memcpy(), memset()
5
6void printCallbackInformation(const struct eCAL_SServiceMethodInformation* method_info_, const char* request_, size_t request_length_, const char* response_, size_t* response_length_)
7{
8 /*
9 The data we get will not be \0 terminated. Hence we need to pass the size to printf.
10 */
11 printf("Method : '%s' called in C\n", method_info_->method_name);
12 printf("Request : %.*s\n", (int)request_length_, request_);
13 printf("Response : %.*s\n", (int)*response_length_, response_);
14 printf("\n");
15}
16
17/*
18 We define the callback function that will be called when a client calls the service method "echo".
19 This callback will simply return the request as the response.
20*/
21int OnEchoCallback(const struct eCAL_SServiceMethodInformation* method_info_, const void* request_, size_t request_length_, void** response_, size_t* response_length_, void* user_argument_)
22{
23 (void)user_argument_;
24
25 /*
26 In order pass the server response properly to the callback API, the underlying memory needs to be allocated
27 with eCAL_Malloc(). The allocation via eCAL_Malloc() is required as the internal memory handler frees the
28 resevered memory after callback execution.
29 */
30 *response_ = eCAL_Malloc(request_length_);
31
32 /*
33 In case of a failure, the value that response_ points to, remains NULL.
34 */
35 if (*response_ == NULL) return -1; // memory allocation failed
36
37 /*
38 The length of response buffer needs to be set accordingly
39 */
40 *response_length_ = request_length_;
41 /*
42 In this example the entire request buffer will be copied over to the response buffer.
43 */
44 memcpy(*response_, request_, request_length_);
45
46 printCallbackInformation(method_info_, (const char*)request_, request_length_, (const char*)(*response_), response_length_);
47
48 return 0;
49}
50
51/*
52 This callback will be called when a client calls the service method "reverse".
53 It will return the request in reverse order as the response.
54*/
55int OnReverseCallback(const struct eCAL_SServiceMethodInformation* method_info_, const void* request_, size_t request_length_, void** response_, size_t* response_length_, void* user_argument_)
56{
57 (void)user_argument_;
58
59 /*
60 In order pass the server response properly to the callback API, the underlying memory needs to be allocated
61 with eCAL_Malloc(). The allocation via eCAL_Malloc() is required as the internal memory handler frees the
62 resevered memory after callback execution.
63 */
64 *response_ = eCAL_Malloc(request_length_);
65
66 /*
67 In case of a failure, the value that response_ points to, remains NULL.
68 */
69 if (*response_ == NULL) return -1; // memory allocation failed
70
71 /*
72 The length of response buffer needs to be set accordingly
73 */
74 *response_length_ = request_length_;
75
76 const char* request = (const char*)request_;
77 char* response = (char*)(*response_);
78
79 for (size_t i = 0; i < request_length_; ++i) {
80 response[i] = request[request_length_ - 1 - i];
81 }
82
83 printCallbackInformation(method_info_, (const char*)request_, request_length_, (const char*)(*response_), response_length_);
84
85 return 0;
86}
87
88int main()
89{
90 printf("------------------\n");
91 printf(" C: Mirror Server\n");
92 printf("------------------\n");
93
94 /*
95 Here we already create the objects we want to work with.
96 Later we will create the server handle and fill the ServiceMethodInformation struct with the required information.
97 */
98 eCAL_ServiceServer *mirror_server;
99 struct eCAL_SServiceMethodInformation echo_method_information;
100 struct eCAL_SServiceMethodInformation reverse_method_information;
101
102 /*
103 As always: initialize the eCAL API and give your process a name.
104 */
105 eCAL_Initialize("mirror server c", NULL, NULL);
106
107 printf("eCAL %s (%s)\n", eCAL_GetVersionString(), eCAL_GetVersionDateString());
108 eCAL_Process_SetState(eCAL_Process_eSeverity_healthy, eCAL_Process_eSeverityLevel_level1, "I feel good!");
109
110 /*
111 Now we create the mirror server and give it the name "mirror".
112 */
113 mirror_server = eCAL_ServiceServer_New("mirror", NULL);
114
115 /*
116 The server will have two methods: "echo" and "reverse".
117 To set a callback, we need to set a ServiceMethodInformation struct as well as the callback function.
118 In our example we will just set the method name of the struct and leave the other two fields empty.
119 */
120 memset(&echo_method_information, 0, sizeof(struct eCAL_SServiceMethodInformation));
121 echo_method_information.method_name = "echo";
122 eCAL_ServiceServer_SetMethodCallback(mirror_server, &echo_method_information, OnEchoCallback, NULL);
123
124 memset(&reverse_method_information, 0, sizeof(struct eCAL_SServiceMethodInformation));
125 reverse_method_information.method_name = "reverse";
126 eCAL_ServiceServer_SetMethodCallback(mirror_server, &reverse_method_information, OnReverseCallback, NULL);
127
128 /*
129 Now we will go in an infinite loop, to wait for incoming service calls that will be handled with the callbacks.
130 */
131 while (eCAL_Ok())
132 {
133 eCAL_Process_SleepMS(500);
134 }
135
136 /*
137 When finished, we need to delete the server handle to clean up properly.
138 */
139 eCAL_ServiceServer_Delete(mirror_server);
140
141 /*
142 After we are done, as always, finalize the eCAL API.
143 */
144 eCAL_Finalize();
145
146 return 0;
147}
1using System;
2using System.Text;
3using Eclipse.eCAL.Core;
4
5public class MirrorServer
6{
7 static void PrintCallbackInformation(string method, byte[] request, byte[] response)
8 {
9 Console.WriteLine("Method : '" + method + "' called in C#");
10 Console.WriteLine("Request : " + Encoding.UTF8.GetString(request));
11 Console.WriteLine("Response : " + Encoding.UTF8.GetString(response));
12 Console.WriteLine();
13 }
14
15 /*
16 We define the callback function that will be called when a client calls the service method "echo".
17 This callback will simply return the request as the response.
18 */
19 static byte[] OnEchoCallback(ServiceMethodInformation methodInfo, byte[] request)
20 {
21 byte[] response = request;
22
23 PrintCallbackInformation(methodInfo.MethodName, request, response);
24
25 return response;
26 }
27
28 /*
29 This callback will be called when a client calls the service method "reverse".
30 It will return the request in reverse order as the response.
31 */
32 static byte[] OnReverseCallback(ServiceMethodInformation methodInfo, byte[] request)
33 {
34 byte[] response = (byte[])request.Clone();
35 Array.Reverse(response);
36
37 PrintCallbackInformation(methodInfo.MethodName, request, response);
38
39 return response;
40 }
41
42 static void Main()
43 {
44 Console.WriteLine("-------------------");
45 Console.WriteLine(" C#: MIRROR SERVER");
46 Console.WriteLine("-------------------");
47
48 /*
49 As always: initialize the eCAL API and give your process a name.
50 */
51 Core.Initialize("mirror server c#");
52
53 Console.WriteLine(string.Format("eCAL {0} ({1})\n", Core.GetVersionString(), Core.GetVersionDateString()));
54
55 /*
56 Now we create the mirror server and give it the name "mirror".
57 */
58 ServiceServer mirrorServer = new ServiceServer("mirror");
59
60 /*
61 The server will have two methods: "echo" and "reverse".
62 To set a callback, we need to set a ServiceMethodInformation struct as well as the callback function.
63 In our example we will just set the method name of the struct and leave the other two fields empty.
64 */
65 ServiceMethodInformation echoMethodInfo = new ServiceMethodInformation();
66 echoMethodInfo.MethodName = "echo";
67 mirrorServer.SetMethodCallback(echoMethodInfo, OnEchoCallback);
68
69 ServiceMethodInformation reverseMethodInfo = new ServiceMethodInformation();
70 reverseMethodInfo.MethodName = "reverse";
71 mirrorServer.SetMethodCallback(reverseMethodInfo, OnReverseCallback);
72
73 /*
74 Now we will go in an infinite loop, to wait for incoming service calls that will be handled with the callbacks.
75 */
76 while (Core.Ok())
77 {
78 System.Threading.Thread.Sleep(500);
79 }
80
81 /*
82 When finished, we need to dispose the server to clean up properly.
83 */
84 mirrorServer.Dispose();
85
86 /*
87 After we are done, as always, finalize the eCAL API.
88 */
89 Core.Terminate();
90 }
91}
1import sys
2import time
3
4import ecal.core.core as ecal_core
5import ecal.core.service as ecal_service
6
7def main():
8 # print eCAL version and date
9 print("eCAL {} ({})\n".format(ecal_core.getversion(), ecal_core.getdate()))
10
11 # initialize eCAL API
12 ecal_core.initialize("py_minimal_service_server")
13
14 # set process state
15 ecal_core.set_process_state(1, 1, "I feel good")
16
17 # create a server for the "DemoService" service
18 server = ecal_service.Server("DemoService")
19
20 # define the server method "foo" function
21 def foo_req_callback(method_name, req_type, resp_type, request):
22 print("'DemoService' method '{}' called with {}".format(method_name, request))
23 return 0, bytes("thank you for calling foo :-)", "ascii")
24
25 # define the server method "ping" function
26 def ping_req_callback(method_name, req_type, resp_type, request):
27 print("'DemoService' method '{}' called with {}".format(method_name, request))
28 return 0, bytes("pong", "ascii")
29
30 # define the server methods and connect them to the callbacks
31 server.add_method_callback("foo", "string", "string", foo_req_callback)
32 server.add_method_callback("ping", "ping_type", "pong_type", ping_req_callback)
33
34 # idle
35 while(ecal_core.ok()):
36 time.sleep(1.0)
37
38 # destroy server
39 server.destroy()
40
41 # finalize eCAL API
42 ecal_core.finalize()
43
44if __name__ == "__main__":
45 main()
7.2.1.2. Mirror Server Files#
├─ C++ │ └─mirror_server.cpp
│ ├─ C │ └─mirror_server_c.c
│ ├─ C# │ └─mirror_server_csharp.cs
│ └─ Python └─minimal_service_server.py
7.2.1.3. Mirror Client#
The client will have some more logic to take care of, as its possible that multiple servers are running with the same service name.
Initialize eCAL
Create a service client with the service name and (optionally) register the functions it can call (in this case “echo” and “mirror”)
Waiting for a server to be available (this is optional and depends on how you want to design your application)
Retrieve all client instances. You can also call it directly on the service client, but if you iterate through all client instances, you are more flexible and could filter out instances you don’t want to call.
Then we call the methodnames with two different calls: with callback (non blocking) and with response (blocking)
Handle the received data (or error status)
As a little extra we also added a little bit more eCAL state handling as in the previous examples.
1#include <ecal/ecal.h>
2
3#include <iostream>
4#include <chrono>
5#include <thread>
6
7/*
8 Helper function to print the service response.
9*/
10void printServiceResponse(const eCAL::SServiceResponse& service_response_)
11{
12 std::string call_state;
13 switch (service_response_.call_state)
14 {
15 case eCAL::eCallState::executed:
16 call_state = "EXECUTED";
17 break;
18 case eCAL::eCallState::failed:
19 call_state = "FAILED";
20 break;
21 default:
22 call_state = "UNKNOWN";
23 break;
24 }
25
26 std::cout << "Received service response in C++: " << call_state << "\n";
27 std::cout << "Method : " << service_response_.service_method_information.method_name << "\n";
28 std::cout << "Response : " << service_response_.response << "\n";
29 std::cout << "Server ID : " << service_response_.server_id.service_id.entity_id << "\n";
30 std::cout << "Host : " << service_response_.server_id.service_id.host_name << "\n";
31 std::cout << "\n";
32}
33
34int main()
35{
36 std::cout << "--------------------" << "\n";
37 std::cout << " C++: MIRROR CLIENT" << "\n";
38 std::cout << "--------------------" << "\n";
39
40 /*
41 As always: initialize the eCAL API and give your process a name.
42 */
43 eCAL::Initialize("mirror client c++");
44
45 std::cout << "eCAL " << eCAL::GetVersionString() << " (" << eCAL::GetVersionDateString() << ")" << "\n";
46 eCAL::Process::SetState(eCAL::Process::eSeverity::warning, eCAL::Process::eSeverityLevel::level1, "Waiting for a service ...");
47
48 /*
49 Create a client that connects to a "mirror" server.
50 It may call the methods "echo" and "reverse"
51 */
52 const eCAL::CServiceClient mirror_client("mirror", { {"echo", {}, {} }, {"reverse", {}, {} } });
53
54 /*
55 This lambda serves as a callback which will be executed when we receive a response from a server.
56 */
57 auto service_response_callback = [](const eCAL::SServiceResponse& service_response_) {
58 printServiceResponse(service_response_);
59 };
60
61 /*
62 We wait until the client is connected to a server,
63 so we don't call methods that are not available.
64 */
65 while (!mirror_client.IsConnected())
66 {
67 std::cout << "Waiting for a service ..." << "\n";
68
69 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
70 }
71
72 /*
73 Now that we are connected, we can set the process state to "healthy" and communicate the connection.
74 */
75 eCAL::Process::SetState(eCAL::Process::eSeverity::healthy, eCAL::Process::eSeverityLevel::level1, "Connected!");
76
77 /*
78 Allow to alternate between the two methods "echo" and "reverse".
79 */
80 unsigned int i = 0;
81 std::vector<std::string> methods = { "echo", "reverse" };
82 bool calls_ok = false;;
83
84 while(eCAL::Ok())
85 {
86 /*
87 Alternate between the two methods "echo" and "reverse".
88 Create the request payload.
89 */
90 std::string method_name = methods[i++ % methods.size()];
91 std::string request("stressed");
92
93 calls_ok = !mirror_client.GetClientInstances().empty();
94
95 /*
96 We iterate now over all client instances and call the methods by name.
97 With this approach we have the option to filter out client instances that we don't want to call.
98 If you want to call either way all instances, then you can use
99
100 mirror_client.CallWithResponse(...)
101 mirror_client.CallWithCallback(...)
102
103 instead of the loop.
104 */
105 for (auto& client_instance : mirror_client.GetClientInstances())
106 {
107 /*
108 Service call: blocking
109 We leave the default timeout value (infinite) for the blocking call.
110 You can change this for a specified timeout in ms.
111 */
112 const auto service_response = client_instance.CallWithResponse(method_name, request, eCAL::CClientInstance::DEFAULT_TIME_ARGUMENT);
113 if (std::get<0>(service_response))
114 {
115 const auto& response_content = std::get<1>(service_response);
116
117 printServiceResponse(response_content);
118 }
119 else
120 {
121 std::cout << "Method blocking call failed." << "\n";
122 calls_ok = false;
123 }
124
125 /*
126 Service call: with callback
127 The callback will be executed when the server has processed the request and sent a response.
128 You can again set a timeout value for an internal waiting time. By default, we wait infinitely.
129 */
130 if (!client_instance.CallWithCallback(method_name, request, service_response_callback, eCAL::CClientInstance::DEFAULT_TIME_ARGUMENT))
131 {
132 std::cout << "Method callback call failed." << "\n";
133 calls_ok = false;
134 }
135 break;
136 }
137
138 /*
139 Now we set the process state according to the result of the service calls.
140 You will see the state in the eCAL Monitor or the eCAL Sys application.
141 */
142 if (calls_ok)
143 {
144 eCAL::Process::SetState(eCAL::Process::eSeverity::healthy, eCAL::Process::eSeverityLevel::level1, "Connected!");
145 }
146 else
147 {
148 eCAL::Process::SetState(eCAL::Process::eSeverity::critical, eCAL::Process::eSeverityLevel::level3, "Calls failed!");
149 }
150
151 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
152 }
153
154 /*
155 After we are done, as always, finalize the eCAL API.
156 */
157 eCAL::Finalize();
158
159 return(0);
160}
1#include <ecal_c/ecal.h>
2#include <ecal_c/service/client.h>
3
4#include <stdio.h> // printf()
5#include <string.h> // strlen
6#include <stdlib.h> // free
7
8/*
9 Helper function to print the service response.
10*/
11void printServiceResponse(const struct eCAL_SServiceResponse* service_response)
12{
13 const char* call_state = NULL;
14
15 switch (service_response->call_state)
16 {
17 case eCAL_eCallState_executed:
18 call_state = "EXECUTED";
19 break;
20 case eCAL_eCallState_failed:
21 call_state = "FAILED";
22 break;
23 default:
24 call_state = "UNKNOWN";
25 break;
26 }
27
28 printf("Received service response in C: %s\n", call_state);
29 printf("Method : %s\n", service_response->service_method_information.method_name);
30 printf("Response : %.*s\n", (int)service_response->response_length, (char*)service_response->response);
31 printf("Server ID : %llu\n", service_response->server_id.service_id.entity_id);
32 printf("Host : %s\n", service_response->server_id.service_id.host_name);
33 printf("\n");
34}
35
36/*
37 Callback function that will be executed when we receive a response from a server.
38*/
39void serviceResponseCallback(const struct eCAL_SServiceResponse* service_response, void* user_data)
40{
41 (void)user_data;
42
43 printServiceResponse(service_response);
44}
45
46
47int main()
48{
49 eCAL_ServiceClient* mirror_client;
50 struct eCAL_SServiceMethodInformation* method_information_set;
51
52 printf("------------------\n");
53 printf(" C: MIRROR CLIENT\n");
54 printf("------------------\n");
55
56 /*
57 As always: initialize the eCAL API and give your process a name.
58 */
59 eCAL_Initialize("mirror client c", NULL, NULL);
60
61 printf("eCAL %s (%s)\n", eCAL_GetVersionString(), eCAL_GetVersionDateString());
62 eCAL_Process_SetState(eCAL_Process_eSeverity_healthy, eCAL_Process_eSeverityLevel_level1, "Waiting for a service ...");
63
64 /*
65 Create a ServiceMethodInformation struct that contains the information about the service methods we want to call.
66 In this case, we want to call the methods "echo" and "reverse".
67 */
68 method_information_set = (struct eCAL_SServiceMethodInformation*)eCAL_Malloc(2 * sizeof(struct eCAL_SServiceMethodInformation));
69 if (method_information_set == NULL)
70 {
71 printf("Memory allocation failed.\n");
72 return -1;
73 }
74
75 memset(method_information_set, 0, 2 * sizeof(struct eCAL_SServiceMethodInformation));
76 method_information_set[0].method_name = "echo";
77 method_information_set[1].method_name = "reverse";
78
79 /*
80 Create a client that connects to a "mirror" server.
81 It may call the methods "echo" and "reverse".
82 */
83 mirror_client = eCAL_ServiceClient_New("mirror", method_information_set, 0, NULL);
84
85 /*
86 Wait until the client is connected to a server,
87 so we don't call methods that are not available.
88 */
89 while (!eCAL_ServiceClient_IsConnected(mirror_client))
90 {
91 printf("Waiting for a service ...\n");
92 eCAL_Process_SleepMS(1000);
93 }
94
95 /*
96 Now that we are connected, we can set the process state to "healthy" and communicate the connection.
97 */
98 eCAL_Process_SetState(eCAL_Process_eSeverity_healthy, eCAL_Process_eSeverityLevel_level1, "Connected!");
99
100 /*
101 Allow alternating between the two methods "echo" and "reverse".
102 */
103 const char* methods[] = { "echo", "reverse" };
104 size_t method_count = sizeof(methods) / sizeof(methods[0]);
105 size_t i = 0;
106 unsigned int calls_ok = 0;
107
108 while (eCAL_Ok())
109 {
110 /*
111 Alternate between the two methods "echo" and "reverse".
112 Create the request payload.
113 */
114 const char* method_name = methods[i++ % method_count];
115 char request[] = "stressed";
116
117 struct eCAL_ClientInstance** client_instances = eCAL_ServiceClient_GetClientInstances(mirror_client);
118 calls_ok = client_instances != NULL && client_instances[0] != NULL;
119
120 /*
121 We iterate now over all client instances and call the methods by name.
122 With this approach we have the option to filter out client instances that we don't want to call.
123 If you want to call either way all instances, then you can use
124
125 eCAL_ServiceClient_CallWithResponse(mirror_client, ...)
126 eCAL_ServiceClient_CallWithCallback(mirror_client, ...)
127
128 instead of the loop.
129 */
130
131 if (client_instances != NULL)
132 {
133 for (size_t j = 0; client_instances[j] != NULL; ++j)
134 {
135 /*
136 Service call: blocking
137 We leave the default timeout value (infinite) for the blocking call.
138 You can change this for a specified timeout in ms.
139 */
140 struct eCAL_SServiceResponse* response = eCAL_ClientInstance_CallWithResponse(client_instances[j], method_name, request, strlen(request), NULL);
141 if (response != NULL)
142 {
143 printServiceResponse(response);
144 eCAL_Free(response);
145 }
146 else
147 {
148 printf("Method blocking call failed.\n");
149 calls_ok = 0;
150 }
151
152 /*
153 Service call: with callback
154 The callback will be executed when the server has processed the request and sent a response.
155 You can again set a timeout value for an internal waiting time. By default, we wait infinitely.
156 */
157 if(eCAL_ClientInstance_CallWithCallback(client_instances[j], method_name, request, strlen(request), serviceResponseCallback, NULL, NULL) != 0)
158 {
159 printf("Method callback call failed.\n");
160 calls_ok = 0;
161 }
162 }
163
164 /*
165 After usage, free the memory from the client instances.
166 */
167 eCAL_ClientInstances_Delete(client_instances);
168 }
169
170 /*
171 Now we set the process state according to the result of the service calls.
172 You will see the state in the eCAL Monitor or the eCAL Sys application.
173 */
174 if (calls_ok != 0)
175 {
176 eCAL_Process_SetState(eCAL_Process_eSeverity_healthy, eCAL_Process_eSeverityLevel_level1, "Connected!");
177 }
178 else
179 {
180 eCAL_Process_SetState(eCAL_Process_eSeverity_critical, eCAL_Process_eSeverityLevel_level3, "Calls failed!");
181 }
182
183 eCAL_Process_SleepMS(1000);
184 }
185
186 /*
187 Don't forget to delete the client handle.
188 */
189 eCAL_ServiceClient_Delete(mirror_client);
190
191 /*
192 After we are done, as always, finalize the eCAL API.
193 */
194 eCAL_Finalize();
195
196 return 0;
197}
1using System;
2using System.Collections.Generic;
3using System.Text;
4using Eclipse.eCAL.Core;
5
6public class MirrorClient
7{
8 /*
9 Helper function to print the service response.
10 */
11 static void PrintServiceResponse(ServiceResponse serviceResponse)
12 {
13 string callState;
14 switch (serviceResponse.CallState)
15 {
16 case CallState.Executed:
17 callState = "EXECUTED";
18 break;
19 case CallState.Failed:
20 callState = "FAILED";
21 break;
22 default:
23 callState = "UNKNOWN";
24 break;
25 }
26
27 Console.WriteLine("Received service response in C: " + callState);
28 Console.WriteLine("Method : " + serviceResponse.MethodInformation.MethodName);
29 Console.WriteLine("Response : " + Encoding.UTF8.GetString(serviceResponse.Response));
30 Console.WriteLine("Server ID : " + serviceResponse.ServerId.EntityID.Id);
31 Console.WriteLine("Host : " + serviceResponse.ServerId.EntityID.HostName);
32 Console.WriteLine();
33 }
34
35 static void Main()
36 {
37 Console.WriteLine("-------------------");
38 Console.WriteLine(" C#: MIRROR CLIENT");
39 Console.WriteLine("-------------------");
40
41 /*
42 As always: initialize the eCAL API and give your process a name.
43 */
44 Core.Initialize("mirror client c#");
45
46 Console.WriteLine(String.Format("eCAL {0} ({1})\n", Core.GetVersionString(), Core.GetVersionDateString()));
47
48 /*
49 Create a client that connects to a "mirror" server.
50 It may call the methods "echo" and "reverse"
51 */
52 ServiceMethodInformationList methodInformationList = new ServiceMethodInformationList();
53 methodInformationList.Methods.Add(new ServiceMethodInformation("echo", new DataTypeInformation(), new DataTypeInformation()));
54 methodInformationList.Methods.Add(new ServiceMethodInformation("reverse", new DataTypeInformation(), new DataTypeInformation()));
55
56 ServiceClient mirrorClient = new ServiceClient("mirror", methodInformationList);
57
58 /*
59 We wait until the client is connected to a server,
60 so we don't call methods that are not available.
61 */
62 while (!mirrorClient.IsConnected())
63 {
64 Console.WriteLine("Waiting for a service ...");
65 System.Threading.Thread.Sleep(1000);
66 }
67
68 /*
69 Allow to alternate between the two methods "echo" and "reverse".
70 */
71 int i = 0;
72 string[] methods = new string[] { "echo", "reverse" };
73
74 while (Core.Ok())
75 {
76 /*
77 Alternate between the two methods "echo" and "reverse".
78 Create the request payload.
79 */
80 string method = methods[i++ % methods.Length];
81 byte[] request = Encoding.UTF8.GetBytes("stressed");
82
83 /*
84 Service call with response
85 */
86 List<ServiceResponse> responseList = mirrorClient.CallWithResponse(method, request, (int)Eclipse.eCAL.Core.ServiceClient.DefaultTimeArgument);
87
88 /*
89 Iterate through all responses and print them.
90 */
91 if (responseList.Count > 0)
92 {
93 foreach (ServiceResponse response in responseList)
94 {
95 PrintServiceResponse(response);
96 }
97 }
98 else
99 {
100 Console.WriteLine("Method call with response failed.");
101 }
102
103 /*
104 Service call with callback
105 */
106 if (!mirrorClient.CallWithCallback(
107 method,
108 request,
109 response => PrintServiceResponse(response),
110 (int)ServiceClient.DefaultTimeArgument)
111 )
112 {
113 Console.WriteLine("Method call with callback failed.");
114 }
115
116 System.Threading.Thread.Sleep(1000);
117 }
118
119 /*
120 When finished, we need to dispose the client to clean up properly.
121 */
122 mirrorClient.Dispose();
123
124 /*
125 After we are done, as always, finalize the eCAL API.
126 */
127 Core.Terminate();
128 }
129}
1import sys
2import time
3
4import ecal.core.core as ecal_core
5import ecal.core.service as ecal_service
6
7def main():
8 # print eCAL version and date
9 print("eCAL {} ({})\n".format(ecal_core.getversion(), ecal_core.getdate()))
10
11 # initialize eCAL API
12 ecal_core.initialize("py_minimal_service_client")
13
14 # set process state
15 ecal_core.set_process_state(1, 1, "I feel good")
16
17 # create a client for the "DemoService" service
18 client = ecal_service.Client("DemoService")
19
20 # define the client response callback to catch server responses
21 def client_resp_callback(service_info, response):
22 if (service_info["call_state"] == "call_state_executed"):
23 print("'DemoService' method '{}' responded : '{}'".format(service_info["method_name"], response))
24 print()
25 else:
26 print("server {} response failed, error : '{}'".format(service_info["host_name"], service_info["error_msg"]))
27 print()
28
29 # and add it to the client
30 client.add_response_callback(client_resp_callback)
31
32 # idle and call service methods
33 i = 0
34 while(ecal_core.ok()):
35 i = i + 1
36 # call foo
37 request = bytes("hello foo {}".format(i), "ascii")
38 print("'DemoService' method 'foo' requested with : {}".format(request))
39 client.call_method("foo", request)
40 time.sleep(0.5)
41 # call ping
42 request = bytes("ping number {}".format(i), "ascii")
43 print("'DemoService' method 'ping' requested with : {}".format(request))
44 client.call_method("ping", request)
45 time.sleep(0.5)
46
47 # destroy client
48 client.destroy()
49
50 # finalize eCAL API
51 ecal_core.finalize()
52
53if __name__ == "__main__":
54 main()
7.2.1.4. Mirror Client Files#
├─ C++ │ └─mirror_client.cpp
│ ├─ C │ └─mirror_client.c
│ ├─ C# │ └─mirror_client_csharp.cs
│ └─ Python └─minimal_service_client.py