1 // Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
2 // This Source Code Form is subject to the terms of the Mozilla Public
3 // License, v. 2.0. If a copy of the MPL was not distributed with this
4 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
6 #include <csignal>
7 #endif
8 #include <chrono>
9 #include <condition_variable>
10 #include <iomanip>
11 #include <iostream>
12 #include <sstream>
13 #include <thread>
14
15 #include <vsomeip/vsomeip.hpp>
16
17 #include "sample-ids.hpp"
18
19 class client_sample {
20 public:
client_sample(bool _use_tcp,bool _be_quiet,uint32_t _cycle)21 client_sample(bool _use_tcp, bool _be_quiet, uint32_t _cycle)
22 : app_(vsomeip::runtime::get()->create_application()),
23 request_(vsomeip::runtime::get()->create_request(_use_tcp)),
24 use_tcp_(_use_tcp),
25 be_quiet_(_be_quiet),
26 cycle_(_cycle),
27 running_(true),
28 blocked_(false),
29 is_available_(false),
30 sender_(std::bind(&client_sample::run, this)) {
31 }
32
init()33 bool init() {
34 if (!app_->init()) {
35 std::cerr << "Couldn't initialize application" << std::endl;
36 return false;
37 }
38
39 std::cout << "Client settings [protocol="
40 << (use_tcp_ ? "TCP" : "UDP")
41 << ":quiet="
42 << (be_quiet_ ? "true" : "false")
43 << ":cycle="
44 << cycle_
45 << "]"
46 << std::endl;
47
48 app_->register_state_handler(
49 std::bind(
50 &client_sample::on_state,
51 this,
52 std::placeholders::_1));
53
54 app_->register_message_handler(
55 vsomeip::ANY_SERVICE, SAMPLE_INSTANCE_ID, vsomeip::ANY_METHOD,
56 std::bind(&client_sample::on_message,
57 this,
58 std::placeholders::_1));
59
60 request_->set_service(SAMPLE_SERVICE_ID);
61 request_->set_instance(SAMPLE_INSTANCE_ID);
62 request_->set_method(SAMPLE_METHOD_ID);
63
64 std::shared_ptr< vsomeip::payload > its_payload = vsomeip::runtime::get()->create_payload();
65 std::vector< vsomeip::byte_t > its_payload_data;
66 for (std::size_t i = 0; i < 10; ++i)
67 its_payload_data.push_back(static_cast<vsomeip::byte_t>(i % 256));
68 its_payload->set_data(its_payload_data);
69 request_->set_payload(its_payload);
70
71 app_->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID,
72 std::bind(&client_sample::on_availability,
73 this,
74 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
75
76 app_->register_availability_handler(SAMPLE_SERVICE_ID + 1, SAMPLE_INSTANCE_ID,
77 std::bind(&client_sample::on_availability,
78 this,
79 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
80 return true;
81 }
82
start()83 void start() {
84 app_->start();
85 }
86
87 #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
88 /*
89 * Handle signal to shutdown
90 */
stop()91 void stop() {
92 running_ = false;
93 blocked_ = true;
94 app_->clear_all_handler();
95 app_->release_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
96 condition_.notify_one();
97 sender_.join();
98 app_->stop();
99 }
100 #endif
101
on_state(vsomeip::state_type_e _state)102 void on_state(vsomeip::state_type_e _state) {
103 if (_state == vsomeip::state_type_e::ST_REGISTERED) {
104 app_->request_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
105 }
106 }
107
on_availability(vsomeip::service_t _service,vsomeip::instance_t _instance,bool _is_available)108 void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) {
109 std::cout << "Service ["
110 << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance
111 << "] is "
112 << (_is_available ? "available." : "NOT available.")
113 << std::endl;
114
115 if (SAMPLE_SERVICE_ID == _service && SAMPLE_INSTANCE_ID == _instance) {
116 if (is_available_ && !_is_available) {
117 is_available_ = false;
118 } else if (_is_available && !is_available_) {
119 is_available_ = true;
120 send();
121 }
122 }
123 }
124
on_message(const std::shared_ptr<vsomeip::message> & _response)125 void on_message(const std::shared_ptr< vsomeip::message > &_response) {
126 std::cout << "Received a response from Service ["
127 << std::setw(4) << std::setfill('0') << std::hex << _response->get_service()
128 << "."
129 << std::setw(4) << std::setfill('0') << std::hex << _response->get_instance()
130 << "] to Client/Session ["
131 << std::setw(4) << std::setfill('0') << std::hex << _response->get_client()
132 << "/"
133 << std::setw(4) << std::setfill('0') << std::hex << _response->get_session()
134 << "]"
135 << std::endl;
136 if (is_available_)
137 send();
138 }
139
send()140 void send() {
141 if (!be_quiet_)
142 {
143 std::lock_guard< std::mutex > its_lock(mutex_);
144 blocked_ = true;
145 condition_.notify_one();
146 }
147 }
148
run()149 void run() {
150 while (running_) {
151 {
152 std::unique_lock<std::mutex> its_lock(mutex_);
153 while (!blocked_) condition_.wait(its_lock);
154 if (is_available_) {
155 app_->send(request_);
156 std::cout << "Client/Session ["
157 << std::setw(4) << std::setfill('0') << std::hex << request_->get_client()
158 << "/"
159 << std::setw(4) << std::setfill('0') << std::hex << request_->get_session()
160 << "] sent a request to Service ["
161 << std::setw(4) << std::setfill('0') << std::hex << request_->get_service()
162 << "."
163 << std::setw(4) << std::setfill('0') << std::hex << request_->get_instance()
164 << "]"
165 << std::endl;
166 blocked_ = false;
167 }
168 }
169 std::this_thread::sleep_for(std::chrono::milliseconds(cycle_));
170 }
171 }
172
173 private:
174 std::shared_ptr< vsomeip::application > app_;
175 std::shared_ptr< vsomeip::message > request_;
176 bool use_tcp_;
177 bool be_quiet_;
178 uint32_t cycle_;
179 std::mutex mutex_;
180 std::condition_variable condition_;
181 bool running_;
182 bool blocked_;
183 bool is_available_;
184
185 std::thread sender_;
186 };
187
188 #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
189 client_sample *its_sample_ptr(nullptr);
handle_signal(int _signal)190 void handle_signal(int _signal) {
191 if (its_sample_ptr != nullptr &&
192 (_signal == SIGINT || _signal == SIGTERM))
193 its_sample_ptr->stop();
194 }
195 #endif
196
main(int argc,char ** argv)197 int main(int argc, char **argv) {
198 bool use_tcp = false;
199 bool be_quiet = false;
200 uint32_t cycle = 1000; // Default: 1s
201
202 std::string tcp_enable("--tcp");
203 std::string udp_enable("--udp");
204 std::string quiet_enable("--quiet");
205 std::string cycle_arg("--cycle");
206
207 int i = 1;
208 while (i < argc) {
209 if (tcp_enable == argv[i]) {
210 use_tcp = true;
211 } else if (udp_enable == argv[i]) {
212 use_tcp = false;
213 } else if (quiet_enable == argv[i]) {
214 be_quiet = true;
215 } else if (cycle_arg == argv[i] && i+1 < argc) {
216 i++;
217 std::stringstream converter;
218 converter << argv[i];
219 converter >> cycle;
220 }
221 i++;
222 }
223
224 client_sample its_sample(use_tcp, be_quiet, cycle);
225 #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
226 its_sample_ptr = &its_sample;
227 signal(SIGINT, handle_signal);
228 signal(SIGTERM, handle_signal);
229 #endif
230 if (its_sample.init()) {
231 its_sample.start();
232 return 0;
233 } else {
234 return 1;
235 }
236 }
237