/*============================================================================*/ /* Copyright (C) huaxu (2022). * * All rights reserved. This software is huaxu property. Duplication * or disclosure without huaxu written authorization is prohibited. * * @file someip_server.hpp * @brief head file of someip service * @author LiuZhimin * @date 2026-02-24 15:20:00 */ /*============================================================================*/ /*=======[R E V I S I O N H I S T O R Y]====================================*/ /* * V0.0.1 20260606 Liuzhimin Initial Version */ /*============================================================================*/ #ifndef SOMEIP_SERVER_HPP #define SOMEIP_SERVER_HPP /*=======[I N C L U D E S]====================================================*/ #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING #include #endif #include #include #include #include #include #include #include #include using namespace std; using namespace vsomeip; /*=======[M A C R O S]========================================================*/ #ifdef USE_LOG_MODULE #include "log_mgt_api.h" #ifdef LOG_TAG_SOMEIP #undef LOG_TAG_SOMEIP #endif #define LOG_TAG_SOMEIP "someip_server" #define someip_log_d(...) \ do \ { \ Log.d(LOG_TAG_SOMEIP, ##__VA_ARGS__); \ } while (0) #define someip_log_i(...) \ do \ { \ Log.i(LOG_TAG_SOMEIP, ##__VA_ARGS__); \ } while (0) #define someip_log_w(...) \ do \ { \ Log.w(LOG_TAG_SOMEIP, ##__VA_ARGS__); \ } while (0) #define someip_log_e(...) \ do \ { \ Log.e(LOG_TAG_SOMEIP, ##__VA_ARGS__); \ } while (0) #else #ifdef LOG_TAG_SOMEIP #undef LOG_TAG_SOMEIP #endif #define LOG_TAG_SOMEIP "someip_server" #define someip_log_d(format, ...) \ do \ { \ printf("D %s ", LOG_TAG_SOMEIP); \ printf(format, ##__VA_ARGS__); \ printf("\n"); \ } while (0) #define someip_log_i(format, ...) \ do \ { \ printf("I %s ", LOG_TAG_SOMEIP); \ printf(format, ##__VA_ARGS__); \ printf("\n"); \ } while (0) #define someip_log_w(format, ...) \ do \ { \ printf("W %s ", LOG_TAG_SOMEIP); \ printf(format, ##__VA_ARGS__); \ printf("\n"); \ } while (0) #define someip_log_e(format, ...) \ do \ { \ printf("E %s ", LOG_TAG_SOMEIP); \ printf(format, ##__VA_ARGS__); \ printf("\n"); \ } while (0) #endif /*=======[P A R A M T Y P E D E F]==========================================*/ typedef std::function(void)> get_response_data_func_t; // typedef std::function(const std::shared_ptr &)> get_notify_data_func_t; typedef std::function(void)> get_notify_data_func_t; // typedef std::function< // bool (const std::shared_ptr &, // const std::shared_ptr &) > epsilon_change_func_t; typedef struct { service_t _service; instance_t _instance; method_t _method; message_type_e _method_type; get_response_data_func_t _get_response_data_func; } offer_method_t; typedef struct { service_t _service; instance_t _instance; method_t _method; } stop_method_t; typedef struct { service_t _service; instance_t _instance; eventgroup_t _eventgroup; event_t _event; event_type_e _type; uint32_t _cycle; /*ms*/ bool _change_resets_cycle; bool _update_on_change; epsilon_change_func_t _epsilon_change_func; reliability_type_e _reliability; get_notify_data_func_t _notify_data_func; } offer_event_t; typedef struct { service_t _service; instance_t _instance; event_t _event; } stop_event_t; typedef struct { service_t _service; instance_t _instance; major_version_t _major; minor_version_t _minor; } offer_service_t; /*=======[E X P O R T D A T A]==============================================*/ /*=======[E X P O R T F U N C T I O N D E C L A R A T I O N S]============*/ extern void my_someip_server_thread_func(void* arg); /*=======[L O C A L D A T A]================================================*/ /*=======[C L A S S I M P L E M E N T A T I O N S]==========================*/ class service { public: service() : app_(vsomeip::runtime::get()->create_application("your_server")) , is_registered_(false) , running_(true) , service_is_offered_(false){ } bool init() { // std::lock_guard its_lock(mutex_); if (!app_->init()) { someip_log_e("Couldn't initialize application"); return false; } app_->register_state_handler( std::bind(&service::on_state, this, std::placeholders::_1)); // { // std::lock_guard its_lock(payload_mutex_); // payload_ = runtime::get()->create_payload(); // } // condition_.notify_one(); someip_log_i("Server app init done."); return true; } void start() { someip_log_i("Server app[%s] start.",app_->get_name().c_str()); app_->start(); } void register_method(service_t _service, instance_t _instance, method_t _method, message_type_e _method_type, const get_response_data_func_t &_get_response_data_func) { someip_log_i("Start a method [0x%04x/0x%04x/0x%04x]",_service, _instance, _method); app_->register_message_handler(_service, _instance, _method, std::bind(&service::on_method_receive, this, std::placeholders::_1, _method_type, _get_response_data_func)); } void on_method_receive(const std::shared_ptr &_request, message_type_e _method_type, const get_response_data_func_t &_get_response_data_func) { someip_log_i("Received a request from client[0x%04x/0x%04x] to service[0x%04x/0x%04x]", _request->get_client(), _request->get_session(), _request->get_service(), _request->get_instance()); if ((nullptr != _get_response_data_func) && (_method_type != message_type_e::MT_REQUEST_NO_RETURN)) { std::shared_ptr _response = runtime::get()->create_response(_request); std::shared_ptr _payload = runtime::get()->create_payload(); std::vector data = _get_response_data_func(); /* _response->set_message_type(message_type_e::MT_RESPONSE);*/ _payload->set_data(data); _response->set_payload(_payload); app_->send(_response); someip_log_i("Send response from [0x%04x/0x%04x] to [0x%04x/0x%04x] length[%d]", _request->get_service(), _request->get_instance(), _request->get_client(), _request->get_session(),_payload->get_length()); } else { /* to execute F/F-method callback function */ someip_log_i("Execcute F/F-method request from [0x%04x/0x%04x]", _request->get_service(), _request->get_instance()); _get_response_data_func(); } } void unregister_method(service_t _service, instance_t _instance, method_t _method){ someip_log_w("Stop a method [0x%04x/0x%04x/0x%04x]",_service, _instance, _method); app_->unregister_message_handler(_service, _instance, _method); } // TODO : _type, _cycle, _reliability define by config file void register_event(service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, event_type_e _type, uint32_t _cycle, bool _change_resets_cycle, bool _update_on_change, epsilon_change_func_t _epsilon_change_func, reliability_type_e _reliability, get_notify_data_func_t _notify_data_func) { std::set groups; groups.insert(_eventgroup); if (!_epsilon_change_func) { std::cerr << "epsilon_change_func is null!" << std::endl; } if (!_notify_data_func) { std::cerr << "_notify_data_func is null!" << std::endl; } app_->offer_event(_service, _instance, _event, groups, _type, std::chrono::milliseconds(_cycle), _change_resets_cycle, _update_on_change, _epsilon_change_func, _reliability); someip_log_i("Start a event [0x%04x/0x%04x/0x%04x/0x%04x], type[%d], cycle[%dms]", _service, _instance, _eventgroup, _event, _type, _cycle); std::thread _notify_event(std::bind(&service::notify_event, this, _service, _instance, _event, _cycle, _update_on_change, _notify_data_func)); _notify_event.detach(); } void notify_event(service_t _service, instance_t _instance, event_t _event, uint32_t _cycle, bool _update_on_change, get_notify_data_func_t _notify_data_func) { someip_log_i("Start event [0x%04x] notify thread.",_event); while (running_) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); /* wait for service offer */ while (!service_is_offered_ && running_) std::this_thread::sleep_for(std::chrono::milliseconds(10)); if (service_is_offered_ && running_) { if (_update_on_change || (0U == _cycle)) { // for update on change /* If data is not empty and changed, to notify */ static std::vector lastData; std::vector notify_data; notify_data.clear(); notify_data = _notify_data_func(); if ((nullptr != _notify_data_func) && (lastData != notify_data)) { lastData = notify_data; std::shared_ptr _payload = runtime::get()->create_payload(); _payload->set_data(notify_data); someip_log_d("Notify event[0x%04x] with data size[%d] payload length[%d].", _event,notify_data.size(), _payload->get_length()); app_->notify(_service, _instance, _event, _payload); } } else // for cycle update { if (nullptr != _notify_data_func) { std::vector notify_data; std::shared_ptr _payload = runtime::get()->create_payload(); notify_data.clear(); notify_data = _notify_data_func(); _payload->set_data(notify_data); someip_log_d("Notify cycle event[0x%04x] with data size[%d] payload length[%d].", _event,notify_data.size(), _payload->get_length()); app_->notify(_service, _instance, _event, _payload); } else{ someip_log_e("event[0x%04x]_notify_data_func is nullptr!!", _event); return; } std::this_thread::sleep_for(std::chrono::milliseconds(_cycle - 1)); } } } someip_log_w("Stop event [0x%04x] notify thread.",_event); return; } void unregister_event(service_t _service, instance_t _instance, event_t _event) { app_->stop_offer_event(_service, _instance, _event); someip_log_i("Stop a event [0x%04x/0x%04x/0x%04x].",_service, _instance, _event); } void start_offer_service(service_t _service, instance_t _instance, major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR) { // std::lock_guard its_lock(notify_mutex_); app_->offer_service(_service, _instance, _major, _minor); // offer service (SD) service_is_offered_ = true; // notify_condition_.notify_one(); someip_log_i("Start offer service [0x%04x/0x%04x].",_service, _instance); } void stop_offer_service(service_t _service, instance_t _instance, major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR) { app_->stop_offer_service(_service, _instance, _major, _minor); service_is_offered_ = false; someip_log_w("Stop offer service [0x%04x/0x%04x].",_service, _instance); } void on_state(state_type_e _state) { someip_log_i("Application [%s] is %s.",app_->get_name().c_str(), (_state == state_type_e::ST_REGISTERED ? "registered" : "deregistered")); if (_state == state_type_e::ST_REGISTERED) { if (!is_registered_) { is_registered_ = true; //condition_.notify_one(); } } else { is_registered_ = false; } } #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING /* * Handle signal to shutdown */ void stop() { running_ = false; //condition_.notify_one(); //notify_condition_.notify_one(); app_->clear_all_handler(); //notify_thread_.join(); for (auto &th: notify_threads_)th.join(); app_->stop(); someip_log_w("Service app stopped."); } #endif private: std::shared_ptr app_; bool is_registered_; //std::mutex mutex_; //std::condition_variable condition_; bool running_; //std::mutex notify_mutex_; //std::condition_variable notify_condition_; bool service_is_offered_; //std::mutex payload_mutex_; //std::shared_ptr payload_; // blocked_ / service_is_offered_ must be initialized before starting the threads! // std::thread offer_thread_; // std::thread notify_thread_; std::vector notify_threads_; }; #endif // SOMEIP_SERVER_HPP