/*============================================================================*/ /* Copyright (C) huaxu (2022). * * All rights reserved. This software is huaxu property. Duplication * or disclosure without huaxu written authorization is prohibited. * * @file someip_client.hpp * @brief head file of someip client * @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 AG_VSOMEIP_CLIENT_HPP #define AG_VSOMEIP_CLIENT_HPP /*=======[I N C L U D E S]====================================================*/ #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING #include #endif #include #include #include #include #include #include #include #include "someip_server_cfg.hpp" 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_client" #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_client" #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)> request_method_func_t; typedef struct { service_t _service; instance_t _instance; method_t _method; request_method_func_t _request_method_func; message_type_e _message_type; message_handler_t _massage_handle_func; } request_method_t; typedef struct { service_t _service; instance_t _instance; eventgroup_t _eventgroup; event_t _event; event_type_e _type; message_handler_t _massage_handle_func; } request_event_t; typedef struct { service_t _service; instance_t _instance; } request_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_client_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 client { public: client(bool _use_tcp, bool _be_quiet, uint32_t _cycle) : app_(runtime::get()->create_application("your_client")), request_(runtime::get()->create_request()), use_tcp_(_use_tcp), //TCP OR UDP be_quiet_(_be_quiet), cycle_(_cycle), running_(true), blocked_(false), is_available_(false), sender_(std::bind(&client::run, this)) { } bool init() { if (!app_->init()) { someip_log_e("Couldn't initialize application"); return false; } someip_log_i("Client settings [protocol=%s:quiet=%s:cycle=%d]", (use_tcp_ ? "TCP" : "UDP"),(be_quiet_ ? "true" : "false"), cycle_); app_->register_state_handler( std::bind(&client::on_state, this, std::placeholders::_1)); //any feed back message app_->register_message_handler( ANY_SERVICE, ANY_INSTANCE, ANY_METHOD, std::bind(&client::on_message, this, std::placeholders::_1)); someip_log_i("Client app init done."); return true; } void start_request_method(service_t _service, instance_t _instance, method_t _method, const request_method_func_t &_request_method_func, message_type_e _message_type, const message_handler_t &_massage_handle_func){ app_->register_availability_handler(_service, _instance, std::bind(&client::on_availability, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); someip_log_i("Send a requset register to method [0x%04x/0x%04x/0x%04x]", _service, _instance, _method); if ((message_type_e::MT_REQUEST_NO_RETURN != _message_type) && (nullptr != _massage_handle_func)) { /* register response massage handler */ app_->register_message_handler(_service, _instance, _method, _massage_handle_func); } /* request thread */ std::thread req_method(std::bind(&client::request_method_func, this, _service, _instance, _method, _message_type, _request_method_func)); req_method.detach(); } void request_method_func(service_t _service, instance_t _instance, method_t _method, message_type_e _message_type, const request_method_func_t &_request_method_func) { if (is_available_){ /* TODO :this available should be one server available, change it bind to server */ if (nullptr != _request_method_func) { std::vector data = _request_method_func(); if (data[0] != byte_t{0}) /* data[0] is request flag */ { std::shared_ptr< message > request = runtime::get()->create_request(); request->set_service(_service); request->set_instance(_instance); request->set_method(_method); request->set_message_type(_message_type); std::shared_ptr payload; std::vector req_data; req_data.assign(data[1],data.size()-1); /* request data: data[1]~... */ payload->set_data(req_data); request->set_payload(payload); app_->send(request); someip_log_i("Client/session [0x%04x/0x%04x] sent a request to Service/instance/method [0x%04x/0x%04x/0x%04x]", request->get_client(),request->get_session(), request->get_service(),request->get_instance(),request->get_method()); } else { /* code */ } } } else{ } } void start_request_event(service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, event_type_e _type, const message_handler_t &_massage_handle_func, major_version_t _major = DEFAULT_MAJOR){ app_->register_availability_handler(_service, _instance, std::bind(&client::on_availability, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); if (nullptr != _massage_handle_func) { /* register response massage handler */ app_->register_message_handler(_service, _instance, _event, _massage_handle_func); } else { someip_log_w("Event [0x%04x/0x%04x/0x%04x/0x%04x] handle function is null", _service, _instance, _eventgroup, _event); } std::set its_groups; its_groups.insert(_eventgroup); app_->request_event(_service, _instance, _event,its_groups,_type); app_->subscribe(_service, _instance, _eventgroup, _major); someip_log_i("Send a request to event [0x%04x/0x%04x/0x%04x/0x%04x]", _service, _instance, _eventgroup, _event); } void stop_request_event(service_t _service, instance_t _instance, event_t _event){ app_->release_event(_service, _instance, _event); someip_log_i("Stop request event [0x%04x/0x%04x/0x%04x]", _service, _instance, _event); } void stop_request_event_group(service_t _service, instance_t _instance, eventgroup_t _eventgroup){ app_->unsubscribe( _service, _instance, _eventgroup); someip_log_i("Stop request event-group [0x%04x/0x%04x/0x%04x]", _service, _instance, _eventgroup); } void start_request_service(service_t _service, instance_t _instance, major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = 0U){ app_->request_service(_service, _instance, _major, _minor); // find_service (SD) //msg_threads_.push_back(std::thread(&client::on_message, this)); // app_->register_message_handler(_service, _instance, ANY_METHOD, // std::bind(&client::on_message, this, std::placeholders::_1)); // app_->register_message_handler( // ANY_SERVICE, _instance, ANY_METHOD, // std::bind(&client::on_message, this, // std::placeholders::_1)); someip_log_i("Start request service [0x%04x/0x%04x].",_service, _instance); } void stop_request_service(service_t _service, instance_t _instance) { app_->release_service(_service, _instance); //is_offered_ = false; someip_log_w("Stop request service [0x%04x/0x%04x].",_service, _instance); } void start() { someip_log_i("Client app[%s] start.",app_->get_name().c_str()); app_->start(); } #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING /* * Handle signal to shutdown */ void stop() { app_->clear_all_handler(); //app_->unsubscribe(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENTGROUP_ID); //app_->release_event(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID); //app_->release_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID); condition_.notify_one(); sender_.join(); //for (auto &th: msg_threads_)th.join(); app_->stop(); } #endif 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")); app_state_ = _state; if (_state == state_type_e::ST_REGISTERED) { // TODO : ... } } void on_availability(service_t _service, instance_t _instance, bool _is_available){ someip_log_i("Service [0x%04x.0x%04x] is %s", _service, _instance, (_is_available ? "available." : "NOT available.")); if (is_available_ && !_is_available){ is_available_ = false; } else if (_is_available && !is_available_){ is_available_ = true; // send(); } else{ } } void on_message(const std::shared_ptr &_response) { std::shared_ptr its_payload =_response->get_payload(); //someip_log_i("Received a message [0x%04x.0x%04x.0x%04x] to Client/Session [0x%04x.0x%04x].", // _response->get_service(), _response->get_instance(), _response->get_method(), // _response->get_client(), _response->get_session()); switch (_response->get_method()) { //case 0x8001: // someip_log_i("------------0x8001---------"); // break; case 0x8002: someip_log_i("------------0x8002---------"); break; case 0x8003: someip_log_i("------------0x8003---------"); break; case 0x8004: someip_log_i("------------0x8004---------"); break; case 0x8005: someip_log_i("------------0x8005---------"); break; case 0x8006: someip_log_i("------------0x8006---------"); break; default: break; } // // TODO : here is received_data // std::vector received_data; // received_data.assign(its_payload->get_data(),its_payload->get_data()+its_payload->get_length()); // std::string data_to_str; // data_to_str.assign(received_data.begin(), received_data.end()); // someip_log_i("Received message lenght[%d] [%s].",its_payload->get_length(), data_to_str.c_str()); } void send() { if (!be_quiet_) { std::lock_guard< std::mutex > its_lock(mutex_); blocked_ = true; condition_.notify_one(); } } //bind with std::thread sender_, below function is send requset to sevice void run() { while (running_) { { std::unique_lock its_lock(mutex_); while (!blocked_) condition_.wait(its_lock); if (is_available_) { app_->send(request_); someip_log_i("Client/Session [0x%04x/0x%04x] sent a request to Service [0x%04x/0x%04x]", request_->get_client(),request_->get_session(), request_->get_service(),request_->get_instance()); blocked_ = false; } } std::this_thread::sleep_for(std::chrono::milliseconds(cycle_)); } } private: std::shared_ptr< application > app_; std::shared_ptr< message > request_; bool use_tcp_; bool be_quiet_; uint32_t cycle_; session_t session_; std::mutex mutex_; std::condition_variable condition_; bool running_; bool blocked_; bool is_available_; state_type_e app_state_; std::thread sender_; //std::vector msg_threads_; }; #endif // AG_VSOMEIP_CLIENT_HPP