feat(soa_server):initial version of soa_server
This commit is contained in:
420
source/soa_server/someip_server.hpp
Normal file
420
source/soa_server/someip_server.hpp
Normal file
@@ -0,0 +1,420 @@
|
||||
/*============================================================================*/
|
||||
/* 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]====================================*/
|
||||
/* <VERSION> <DATE> <AUTHOR> <REVISION LOG>
|
||||
* 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 <csignal>
|
||||
#endif
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#include <vsomeip/vsomeip.hpp>
|
||||
|
||||
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<std::vector<byte_t>(void)> get_response_data_func_t;
|
||||
// typedef std::function<std::vector<byte_t>(const std::shared_ptr<bool> &)> get_notify_data_func_t;
|
||||
typedef std::function<std::vector<byte_t>(void)> get_notify_data_func_t;
|
||||
// typedef std::function<
|
||||
// bool (const std::shared_ptr<payload> &,
|
||||
// const std::shared_ptr<payload> &) > 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("soa_server"))
|
||||
, is_registered_(false)
|
||||
, running_(true)
|
||||
, service_is_offered_(false){
|
||||
}
|
||||
|
||||
bool init()
|
||||
{
|
||||
// std::lock_guard<std::mutex> 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<std::mutex> 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<message> &_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<message> _response = runtime::get()->create_response(_request);
|
||||
std::shared_ptr<payload> _payload = runtime::get()->create_payload();
|
||||
std::vector<byte_t> 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<eventgroup_t> 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<byte_t> lastData;
|
||||
std::vector<byte_t> 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> _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<byte_t> notify_data;
|
||||
std::shared_ptr<payload> _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<std::mutex> 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<application> 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> payload_;
|
||||
|
||||
// blocked_ / service_is_offered_ must be initialized before starting the threads!
|
||||
// std::thread offer_thread_;
|
||||
// std::thread notify_thread_;
|
||||
std::vector<std::thread> notify_threads_;
|
||||
};
|
||||
|
||||
#endif // SOMEIP_SERVER_HPP
|
||||
Reference in New Issue
Block a user