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 #include <mutex>
15
16 #include <vsomeip/vsomeip.hpp>
17
18 #include "sample-ids.hpp"
19
20 class service_sample {
21 public:
service_sample(bool _use_tcp,uint32_t _cycle)22 service_sample(bool _use_tcp, uint32_t _cycle) :
23 app_(vsomeip::runtime::get()->create_application()),
24 is_registered_(false),
25 use_tcp_(_use_tcp),
26 cycle_(_cycle),
27 blocked_(false),
28 running_(true),
29 is_offered_(false),
30 offer_thread_(std::bind(&service_sample::run, this)),
31 notify_thread_(std::bind(&service_sample::notify, this)) {
32 }
33
init()34 bool init() {
35 std::lock_guard<std::mutex> its_lock(mutex_);
36
37 if (!app_->init()) {
38 std::cerr << "Couldn't initialize application" << std::endl;
39 return false;
40 }
41 app_->register_state_handler(
42 std::bind(&service_sample::on_state, this,
43 std::placeholders::_1));
44
45 app_->register_message_handler(
46 SAMPLE_SERVICE_ID,
47 SAMPLE_INSTANCE_ID,
48 SAMPLE_GET_METHOD_ID,
49 std::bind(&service_sample::on_get, this,
50 std::placeholders::_1));
51
52 app_->register_message_handler(
53 SAMPLE_SERVICE_ID,
54 SAMPLE_INSTANCE_ID,
55 SAMPLE_SET_METHOD_ID,
56 std::bind(&service_sample::on_set, this,
57 std::placeholders::_1));
58
59 std::set<vsomeip::eventgroup_t> its_groups;
60 its_groups.insert(SAMPLE_EVENTGROUP_ID);
61 app_->offer_event(
62 SAMPLE_SERVICE_ID,
63 SAMPLE_INSTANCE_ID,
64 SAMPLE_EVENT_ID,
65 its_groups,
66 vsomeip::event_type_e::ET_FIELD, std::chrono::milliseconds::zero(),
67 false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
68 {
69 std::lock_guard<std::mutex> its_lock(payload_mutex_);
70 payload_ = vsomeip::runtime::get()->create_payload();
71 }
72
73 blocked_ = true;
74 condition_.notify_one();
75 return true;
76 }
77
start()78 void start() {
79 app_->start();
80 }
81
82 #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
83 /*
84 * Handle signal to shutdown
85 */
stop()86 void stop() {
87 running_ = false;
88 blocked_ = true;
89 condition_.notify_one();
90 notify_condition_.notify_one();
91 app_->clear_all_handler();
92 stop_offer();
93 offer_thread_.join();
94 notify_thread_.join();
95 app_->stop();
96 }
97 #endif
98
offer()99 void offer() {
100 std::lock_guard<std::mutex> its_lock(notify_mutex_);
101 app_->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
102 is_offered_ = true;
103 notify_condition_.notify_one();
104 }
105
stop_offer()106 void stop_offer() {
107 app_->stop_offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
108 is_offered_ = false;
109 }
110
on_state(vsomeip::state_type_e _state)111 void on_state(vsomeip::state_type_e _state) {
112 std::cout << "Application " << app_->get_name() << " is "
113 << (_state == vsomeip::state_type_e::ST_REGISTERED ?
114 "registered." : "deregistered.") << std::endl;
115
116 if (_state == vsomeip::state_type_e::ST_REGISTERED) {
117 if (!is_registered_) {
118 is_registered_ = true;
119 }
120 } else {
121 is_registered_ = false;
122 }
123 }
124
on_get(const std::shared_ptr<vsomeip::message> & _message)125 void on_get(const std::shared_ptr<vsomeip::message> &_message) {
126 std::shared_ptr<vsomeip::message> its_response
127 = vsomeip::runtime::get()->create_response(_message);
128 {
129 std::lock_guard<std::mutex> its_lock(payload_mutex_);
130 its_response->set_payload(payload_);
131 }
132 app_->send(its_response);
133 }
134
on_set(const std::shared_ptr<vsomeip::message> & _message)135 void on_set(const std::shared_ptr<vsomeip::message> &_message) {
136 std::shared_ptr<vsomeip::message> its_response
137 = vsomeip::runtime::get()->create_response(_message);
138 {
139 std::lock_guard<std::mutex> its_lock(payload_mutex_);
140 payload_ = _message->get_payload();
141 its_response->set_payload(payload_);
142 }
143
144 app_->send(its_response);
145 app_->notify(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID,
146 SAMPLE_EVENT_ID, payload_);
147 }
148
run()149 void run() {
150 std::unique_lock<std::mutex> its_lock(mutex_);
151 while (!blocked_)
152 condition_.wait(its_lock);
153
154 bool is_offer(true);
155 while (running_) {
156 if (is_offer)
157 offer();
158 else
159 stop_offer();
160
161 for (int i = 0; i < 10 && running_; i++)
162 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
163
164 is_offer = !is_offer;
165 }
166 }
167
notify()168 void notify() {
169 std::shared_ptr<vsomeip::message> its_message
170 = vsomeip::runtime::get()->create_request(use_tcp_);
171
172 its_message->set_service(SAMPLE_SERVICE_ID);
173 its_message->set_instance(SAMPLE_INSTANCE_ID);
174 its_message->set_method(SAMPLE_SET_METHOD_ID);
175
176 vsomeip::byte_t its_data[10];
177 uint32_t its_size = 1;
178
179 while (running_) {
180 std::unique_lock<std::mutex> its_lock(notify_mutex_);
181 while (!is_offered_ && running_)
182 notify_condition_.wait(its_lock);
183 while (is_offered_ && running_) {
184 if (its_size == sizeof(its_data))
185 its_size = 1;
186
187 for (uint32_t i = 0; i < its_size; ++i)
188 its_data[i] = static_cast<uint8_t>(i);
189
190 {
191 std::lock_guard<std::mutex> its_lock(payload_mutex_);
192 payload_->set_data(its_data, its_size);
193
194 std::cout << "Setting event (Length=" << std::dec << its_size << ")." << std::endl;
195 app_->notify(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, payload_);
196 }
197
198 its_size++;
199
200 std::this_thread::sleep_for(std::chrono::milliseconds(cycle_));
201 }
202 }
203 }
204
205 private:
206 std::shared_ptr<vsomeip::application> app_;
207 bool is_registered_;
208 bool use_tcp_;
209 uint32_t cycle_;
210
211 std::mutex mutex_;
212 std::condition_variable condition_;
213 bool blocked_;
214 bool running_;
215
216 std::mutex notify_mutex_;
217 std::condition_variable notify_condition_;
218 bool is_offered_;
219
220 std::mutex payload_mutex_;
221 std::shared_ptr<vsomeip::payload> payload_;
222
223 // blocked_ / is_offered_ must be initialized before starting the threads!
224 std::thread offer_thread_;
225 std::thread notify_thread_;
226 };
227
228 #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
229 service_sample *its_sample_ptr(nullptr);
handle_signal(int _signal)230 void handle_signal(int _signal) {
231 if (its_sample_ptr != nullptr &&
232 (_signal == SIGINT || _signal == SIGTERM))
233 its_sample_ptr->stop();
234 }
235 #endif
236
main(int argc,char ** argv)237 int main(int argc, char **argv) {
238 bool use_tcp = false;
239 uint32_t cycle = 1000; // default 1s
240
241 std::string tcp_enable("--tcp");
242 std::string udp_enable("--udp");
243 std::string cycle_arg("--cycle");
244
245 for (int i = 1; i < argc; i++) {
246 if (tcp_enable == argv[i]) {
247 use_tcp = true;
248 break;
249 }
250 if (udp_enable == argv[i]) {
251 use_tcp = false;
252 break;
253 }
254
255 if (cycle_arg == argv[i] && i + 1 < argc) {
256 i++;
257 std::stringstream converter;
258 converter << argv[i];
259 converter >> cycle;
260 }
261 }
262
263 service_sample its_sample(use_tcp, cycle);
264 #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
265 its_sample_ptr = &its_sample;
266 signal(SIGINT, handle_signal);
267 signal(SIGTERM, handle_signal);
268 #endif
269 if (its_sample.init()) {
270 its_sample.start();
271 return 0;
272 } else {
273 return 1;
274 }
275 }
276