SOME/IP 协议
软件开发定制定制上一篇介绍了使用AndroidStudio来编译vsomeip协议栈,这次文章,软件开发定制定制来熟悉一下如何使用vsomeip软件开发定制定制协议栈来实现局域网两软件开发定制定制台机器之间的通讯。
常用API
软件开发定制定制之前在介绍SOME/IP软件开发定制定制协议的时候有提到过SOME/IP软件开发定制定制中有三个比较重要的概念,软件开发定制定制分别是属性(Field), 方法(Method), 以及事件(Event),这里再重复的点一下,带着这个概念去理解API可能会更加深刻:
方法(Method):类似于我们写java类中的定义的函数,函数可以有返回值,可以没有返回值。一个类的实例中的公共方法可以被其他模块调用。vsomeip中的方法也是如此,无返回值的叫做FF方法,有返回值的叫做RR方法。
事件(Event):事件就类似于java中的监听器,当有模块触发回调的时候,监听方能够及时得到响应。事件可以周期性触发(Cycle change),对于属性事件来说,还能定义在值变化时触发(Update on change),以及更新值大于(当前属性值 + ε)时触发(Epsilon change )
属性:这个就更好理解了,类似于java类中定义的属性,有get,set方法,如果不是只读属性,那么其还包括一个值变化的事件。
下图是vsomeip协议栈中一些常见的API列表以及方法的功能。
接下来我们就需要通过一个Demo来熟悉使用这些API了,那么结合上面介绍的概念,我们准备实现如下一个场景:
硬件环境:
两台可联网的Android设备,且均在一个局域网内。
服务端IP地址:172.17.6.41 网关:255.255.255.0客户端IP地址:172.17.6.95 网关:255.255.255.0
- 1
- 2
实现功能:
- 服务端提供一个属性(可读可写可监听),客户端可读,可改变该值,可监听该值变化
- 服务端提供一个方法,收到客户端调用方法后打印一条日志
- 服务端提供一个事件,且每隔1s触发事件通知,客户端监听到该事件后打印日志
接下来开始实现
定义公共类
Common.h
#ifndef NATIVETEST_COMMON_H#define NATIVETEST_COMMON_H#include <vsomeip/vsomeip.hpp>#define SERVICE_ID 0x0001 //服务ID#define INSTANCE_ID 0x0001 //服务实例ID#define METHOD_ID_FIELD_SET 0x1000 //属性SET方法ID#define METHOD_ID_FIELD_GET 0x1001 //属性GET方法ID#define EVENT_ID_FIELD_NOTIFY 0x2000 //属性事件ID#define METHOD_ID_FUNC_CALL 0x1002 //客户端调用服务端方法ID#define EVENT_ID_ONLY_NOTIFY_0 0x2001 //服务端事件0#define EVENT_GROUP_ID_1 0x0001 //事件组1//打印日志#include <android/log.h>#define TAG "vsomeip-test"#define LOGV(format, args...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, "[%s:%d]" format, basename(__FILE__), __LINE__, ##args)#define LOGD(format, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, "[%s:%d]" format, basename(__FILE__), __LINE__, ##args)#define LOGI(format, args...) __android_log_print(ANDROID_LOG_INFO, TAG, "[%s:%d]" format, basename(__FILE__), __LINE__, ##args)#define LOGW(format, args...) __android_log_print(ANDROID_LOG_WARN, TAG, "[%s:%d]" format, basename(__FILE__), __LINE__, ##args)#define LOGE(format, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, "[%s:%d]" format, basename(__FILE__), __LINE__, ##args)#endif //NATIVETEST_COMMON_H
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
创建服务端
定义头文件 Server.h,内容比较简单,相关功能可以看注释
#ifndef NATIVETEST_SERVER_H#define NATIVETEST_SERVER_H#include <unistd.h>#include "thread"#include "Common.h"class Server {public: Server() : rtm_(vsomeip::runtime::get()), app_(rtm_->create_application("Server")){ } ~Server() = default; //初始化Server void ready(); //启动Server void start(); //运行时环境 std::shared_ptr<vsomeip::runtime> rtm_; //服务端application std::shared_ptr<vsomeip::application> app_;private: //属性值 uint32_t field_; //application初始化状态回调 void stateHandler(vsomeip::state_type_e state); //服务实例可用状态回调 void availableHandler(vsomeip::service_t service_, vsomeip::instance_t instance_, bool isAvailable); //报文回调 void messageHandler(const std::shared_ptr<vsomeip::message>& message_); //事件订阅状态回调 bool subscriptionHandler(vsomeip::client_t, bool subscribed); //供客户端调用的方法 void callMethod(int value);};#endif //NATIVETEST_SERVER_H
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
Server端实现:
//// Created by Gaddi//#include "Server.h"void Server::ready() { if(app_){ if(!app_->init()){ LOGE("cannot init the application"); return; } //注册服务实例可用状态回调 app_->register_availability_handler(SERVICE_ID, INSTANCE_ID, std::bind(&Server::availableHandler, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); //注册状态变化回调 app_->register_state_handler(std::bind(&Server::stateHandler, this, std::placeholders::_1)); //注册消息接收回调, 这里我们主要模拟三个属性的(SET,GET), 以及单纯的FUNC执行 app_->register_message_handler(SERVICE_ID, INSTANCE_ID, METHOD_ID_FIELD_GET,std::bind(&Server::messageHandler, this, std::placeholders::_1)); app_->register_message_handler(SERVICE_ID, INSTANCE_ID, METHOD_ID_FIELD_SET,std::bind(&Server::messageHandler, this, std::placeholders::_1)); app_->register_message_handler(SERVICE_ID, INSTANCE_ID, METHOD_ID_FUNC_CALL,std::bind(&Server::messageHandler, this, std::placeholders::_1)); //注册客户端订阅事件组 app_->register_subscription_handler(SERVICE_ID, INSTANCE_ID, EVENT_GROUP_ID_1, std::bind(&Server::subscriptionHandler, this, std::placeholders::_1, std::placeholders::_4)); //注册事件 std::set<vsomeip::eventgroup_t> group_set_1; group_set_1.insert(EVENT_GROUP_ID_1); app_->offer_event(SERVICE_ID, INSTANCE_ID, EVENT_ID_FIELD_NOTIFY, group_set_1, vsomeip::event_type_e::ET_EVENT, std::chrono::milliseconds::zero(), false, true, nullptr, vsomeip::reliability_type_e::RT_UNRELIABLE); app_->offer_event(SERVICE_ID, INSTANCE_ID, EVENT_ID_ONLY_NOTIFY_0, group_set_1, vsomeip::event_type_e::ET_EVENT, std::chrono::milliseconds::zero(), false, true, nullptr, vsomeip::reliability_type_e::RT_UNRELIABLE); LOGE("ready done for server"); }}void Server::start() { if(app_){ LOGE("start for server"); app_->start(); LOGE("start done for server"); }}/** * 当客户端订阅成功后,服务端每隔5s触发通知 * @param srv */static void offerEventCycle(Server* srv){ const int size = 5; uint16_t v = 0; while(true){ vsomeip_v3::byte_t* data_ = new vsomeip_v3::byte_t(size); for(int i=0; i<size; i++){ data_[i] = v + i; } v++; std::shared_ptr<vsomeip::payload> payload_ = srv->rtm_->create_payload(); payload_->set_data(data_, size); srv->app_->notify(SERVICE_ID, INSTANCE_ID, EVENT_ID_ONLY_NOTIFY_0, payload_, true); delete data_; sleep(5); if(v == 10){ break; } }}void Server::availableHandler(vsomeip::service_t service_, vsomeip::instance_t instance_, bool isAvailable) { LOGE("%s received service = %02X , instance = %02X, isAvailable = %d", __func__ , service_ , instance_, isAvailable);}void Server::messageHandler(const std::shared_ptr<vsomeip::message> &message_) { if(message_){ LOGE("Server %s received service = %02X , instance = %02X, type = %hhu", __func__ , message_->get_service(), message_->get_instance(), message_->get_message_type()); if(message_->get_service() == SERVICE_ID && message_->get_instance() == INSTANCE_ID){ switch(message_->get_method()){ case METHOD_ID_FUNC_CALL:{ std::shared_ptr<vsomeip::payload> payload_ = message_->get_payload(); if(payload_){ int val = payload_->get_data()[0]; callMethod(val); } }break; case METHOD_ID_FIELD_SET:{ //获取客户端传递过来的数据 std::shared_ptr<vsomeip::payload> payload_ = message_->get_payload(); bool changed = false; if(payload_){ uint32_t val = payload_->get_data()[0]; if(field_ != val){ field_ = val; changed = true; } //设置属性后,回复OK if(message_->get_message_type() == vsomeip::message_type_e::MT_REQUEST){ std::shared_ptr<vsomeip::message> response_ = rtm_->create_response(message_); app_->send(response_); } if(changed){ std::shared_ptr<vsomeip::payload> p_ = rtm_->create_payload(); vsomeip::byte_t* data_ = new vsomeip::byte_t[1]; data_[0] = field_; p_->set_data(data_, 1); app_->notify(SERVICE_ID, INSTANCE_ID, EVENT_ID_FIELD_NOTIFY, p_); delete[] data_; } } } break; case METHOD_ID_FIELD_GET:{ //回复属性值field给到请求的客户端 LOGE("The client call field get val"); std::shared_ptr<vsomeip::message> response_ = rtm_->create_response(message_); uint8_t size = 1; vsomeip::byte_t* data_ = new vsomeip::byte_t[size]; data_[0] = field_; std::shared_ptr<vsomeip::payload> payload_ = rtm_->create_payload(data_, size); response_->set_payload(payload_); app_->send(response_); delete[] data_; } break; } } }}bool Server::subscriptionHandler(vsomeip::client_t client_, bool subscribed) { LOGE("%s received client_t = %02X , subscribed = %d",__func__ ,client_,subscribed); //客户端订阅成功,启动一个线程来间隔5s广播事件 if(subscribed){ std::thread execute(&offerEventCycle, this); execute.detach(); } return true;}void Server::stateHandler(vsomeip::state_type_e state) { LOGE("%s received state_type_e = %hhu",__func__ ,state); if(state == vsomeip::state_type_e::ST_REGISTERED){ app_->offer_service(SERVICE_ID, INSTANCE_ID); }}void Server::callMethod(int value) { LOGE("%s received param = %d", __func__ , value);}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
创建客户端
定义Client.h 实现如下内容
#ifndef NATIVETEST_CLIENT_H#define NATIVETEST_CLIENT_H#include <unistd.h>#include "Common.h"class Client {public: Client() : rtm_(vsomeip::runtime::get()), app_(rtm_->create_application("Client")){ } ~Client() = default; void ready(); void start(); void callMethod(uint8_t value); void callSetField(uint8_t field); void callGetField();protected: void stateHandler(vsomeip::state_type_e state); void availableHandler(vsomeip::service_t service_, vsomeip::instance_t instance_, bool isAvailable); void messageHandler(const std::shared_ptr<vsomeip::message>& message_);private: std::shared_ptr<vsomeip::runtime> rtm_; std::shared_ptr<vsomeip::application> app_;};#endif //NATIVETEST_CLIENT_H
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
新建Client.cpp,实现Client.h中的接口
#include "Client.h"void Client::ready() { if(!app_->init()){ LOGE("cannot init the application"); return; } //注册初始化回调 app_->register_state_handler(std::bind(&Client::stateHandler, this, std::placeholders::_1)); //注册服务实例发现状态回调 app_->register_availability_handler(SERVICE_ID, INSTANCE_ID, std::bind(&Client::availableHandler, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); //注册消息回调 app_->register_message_handler(SERVICE_ID, INSTANCE_ID, vsomeip::ANY_METHOD, std::bind(&Client::messageHandler, this, std::placeholders::_1));}void Client::start() { if(app_){ app_->start(); }}void Client::stateHandler(vsomeip::state_type_e state) { LOGE("Client %s received state_type_e = %hhu", __func__ , state); //初始化成功之后,请求服务 if(state == vsomeip::state_type_e::ST_REGISTERED){ app_->request_service(SERVICE_ID, INSTANCE_ID); }}void Client::availableHandler(vsomeip::service_t service_, vsomeip::instance_t instance_, bool isAvailable) { LOGE("Client %s received service = %02X , instance = %02X, isAvailable = %d", __func__ , service_ , instance_, isAvailable); if(isAvailable){ //请求事件 std::set<vsomeip::eventgroup_t> group_1; group_1.insert(EVENT_GROUP_ID_1); app_->request_event(SERVICE_ID, INSTANCE_ID, EVENT_ID_FIELD_NOTIFY, group_1, vsomeip::event_type_e::ET_EVENT, vsomeip::reliability_type_e::RT_UNRELIABLE); app_->request_event(SERVICE_ID, INSTANCE_ID, EVENT_ID_ONLY_NOTIFY_0, group_1, vsomeip::event_type_e::ET_EVENT, vsomeip::reliability_type_e::RT_UNRELIABLE); //订阅事件 app_->subscribe(SERVICE_ID, INSTANCE_ID, EVENT_GROUP_ID_1); }}void Client::messageHandler(const std::shared_ptr<vsomeip::message> &message_) { if(message_){ LOGE("Client %s received service = %02X , instance = %02X, type = %hhu", __func__ , message_->get_service(), message_->get_instance(), message_->get_message_type()); switch(message_->get_method()){ case METHOD_ID_FIELD_GET:{ LOGE("Client get field: %d", message_->get_payload()->get_data()[0]); }break; case METHOD_ID_FIELD_SET:{ bool isOk = message_->get_return_code() == vsomeip::return_code_e::E_OK; LOGE("Client set field result: %d", isOk); }break; case EVENT_ID_FIELD_NOTIFY:{ std::shared_ptr<vsomeip::payload> payload_ = message_->get_payload(); if(payload_){ LOGE("Client received field changed event, the field is %d", payload_->get_data()[0]); } }break; case EVENT_ID_ONLY_NOTIFY_0:{ std::shared_ptr<vsomeip::payload> payload_ = message_->get_payload(); if(payload_){ uint16_t size = payload_->get_length(); vsomeip::byte_t* data = payload_->get_data(); LOGE("Client received event, payload is: "); for(int i=0; i< size; i++){ LOGE("%02X", data[i]); } } }break; } }}//调用服务端的方法void Client::callMethod(uint8_t value) { std::shared_ptr<vsomeip::message> msg_ = rtm_->create_request(false); msg_->set_service(SERVICE_ID); msg_->set_instance(INSTANCE_ID); msg_->set_method(METHOD_ID_FUNC_CALL); msg_->set_message_type(vsomeip::message_type_e::MT_REQUEST_NO_RETURN); vsomeip::byte_t* data_ = new vsomeip::byte_t[1]; data_[0] = value; std::shared_ptr<vsomeip::payload> method_ = rtm_->create_payload(data_, 1); msg_->set_payload(method_); app_->send(msg_); delete[] data_;}//调用服务端的setField方法void Client::callSetField(uint8_t field) { std::shared_ptr<vsomeip::message> msg_ = rtm_->create_request(false); msg_->set_service(SERVICE_ID); msg_->set_instance(INSTANCE_ID); msg_->set_method(METHOD_ID_FIELD_SET); vsomeip::byte_t* data_ = new vsomeip::byte_t[1]; data_[0] = field; std::shared_ptr<vsomeip::payload> method_ = rtm_->create_payload(data_, 1); msg_->set_payload(method_); app_->send(msg_); delete[] data_;}//调用服务端属性Get方法void Client::callGetField() { std::shared_ptr<vsomeip::message> msg_ = rtm_->create_request(false); msg_->set_service(SERVICE_ID); msg_->set_instance(INSTANCE_ID); msg_->set_method(METHOD_ID_FIELD_GET); app_->send(msg_);}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
启动运行
初始化Server与Client, 并执行setField, getField, callMethod函数,
新建native-lib.cpp文件,填入如下内容:
#include <jni.h>#include <string>#include <thread>#include <unistd.h>#include "Server.h"#include "Client.h"Server* server;Client* client;static int val = 1;extern "C" JNIEXPORT void JNICALLJava_com_beantechs_nativetest_MainActivity_startServer(JNIEnv*,jobject /* this */) { if(!server){ server = new Server(); server->ready(); server->start(); }}extern "C" JNIEXPORT void JNICALLJava_com_beantechs_nativetest_MainActivity_startClient(JNIEnv*,jobject /* this */) { if(!client) { client = new Client(); client->ready(); client->start(); }}extern "C" JNIEXPORT void JNICALLJava_com_beantechs_nativetest_MainActivity_setField(JNIEnv*,jobject /* this */) { if(client) { client->callSetField(val); val ++; }}extern "C" JNIEXPORT void JNICALLJava_com_beantechs_nativetest_MainActivity_getField(JNIEnv*,jobject /* this */) { if(client) { client->callGetField(); }}extern "C" JNIEXPORT void JNICALLJava_com_beantechs_nativetest_MainActivity_callMethod(JNIEnv*,jobject /* this */) { if(client) { client->callMethod(99); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
然后在上层kotlin代码中依次执行如下函数:
external fun startServer() external fun startClient() external fun getField() external fun setField() external fun callMethod() companion object { // Used to load the 'nativetest' library on application startup. init { System.loadLibrary("nativetest") } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
启动客户端后,可以看到如下打印,流程均已成功执行
2022-07-18 11:29:53.409 10477-10516/com.beantechs.nativetest1 E/vsomeip-test: [Server.cpp:55]ready done for server2022-07-18 11:29:53.409 10477-10516/com.beantechs.nativetest1 E/vsomeip-test: [Server.cpp:61]start for server2022-07-18 11:29:53.411 10477-10517/com.beantechs.nativetest1 E/vsomeip-test: [Server.cpp:97]availableHandler received service = 01 , instance = 01, isAvailable = 02022-07-18 11:29:53.411 10477-10517/com.beantechs.nativetest1 E/vsomeip-test: [Server.cpp:173]stateHandler received state_type_e = 02022-07-18 11:29:53.411 10477-10517/com.beantechs.nativetest1 E/vsomeip-test: [Server.cpp:97]availableHandler received service = 01 , instance = 01, isAvailable = 12022-07-18 11:29:55.305 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:48]Client availableHandler received service = 01 , instance = 01, isAvailable = 02022-07-18 11:29:55.305 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:36]Client stateHandler received state_type_e = 02022-07-18 11:29:55.317 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:48]Client availableHandler received service = 01 , instance = 01, isAvailable = 12022-07-18 11:29:55.319 10477-10516/com.beantechs.nativetest1 E/vsomeip-test: [Server.cpp:163]subscriptionHandler received client_t = 101 , subscribed = 12022-07-18 11:29:55.323 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:70]Client messageHandler received service = 01 , instance = 01, type = 22022-07-18 11:29:55.323 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:94]Client received event, payload is: 2022-07-18 11:29:55.323 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]002022-07-18 11:29:55.323 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]012022-07-18 11:29:55.323 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]022022-07-18 11:29:55.323 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]032022-07-18 11:29:55.323 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]042022-07-18 11:29:58.477 10477-10517/com.beantechs.nativetest1 E/vsomeip-test: [Server.cpp:106]Server messageHandler received service = 01 , instance = 01, type = 12022-07-18 11:29:58.477 10477-10517/com.beantechs.nativetest1 E/vsomeip-test: [Server.cpp:180]callMethod received param = 992022-07-18 11:30:00.325 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:70]Client messageHandler received service = 01 , instance = 01, type = 22022-07-18 11:30:00.325 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:94]Client received event, payload is: 2022-07-18 11:30:00.325 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]012022-07-18 11:30:00.325 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]022022-07-18 11:30:00.325 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]032022-07-18 11:30:00.325 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]042022-07-18 11:30:00.325 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]052022-07-18 11:30:00.591 10477-10517/com.beantechs.nativetest1 E/vsomeip-test: [Server.cpp:106]Server messageHandler received service = 01 , instance = 01, type = 02022-07-18 11:30:00.592 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:70]Client messageHandler received service = 01 , instance = 01, type = 1282022-07-18 11:30:00.592 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:79]Client set field result: 12022-07-18 11:30:00.592 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:70]Client messageHandler received service = 01 , instance = 01, type = 22022-07-18 11:30:00.592 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:85]Client received field changed event, the field is 12022-07-18 11:30:03.029 10477-10517/com.beantechs.nativetest1 E/vsomeip-test: [Server.cpp:106]Server messageHandler received service = 01 , instance = 01, type = 02022-07-18 11:30:03.029 10477-10517/com.beantechs.nativetest1 E/vsomeip-test: [Server.cpp:147]The client call field get val2022-07-18 11:30:03.030 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:70]Client messageHandler received service = 01 , instance = 01, type = 1282022-07-18 11:30:03.030 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:74]Client get field: 12022-07-18 11:30:05.327 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:70]Client messageHandler received service = 01 , instance = 01, type = 22022-07-18 11:30:05.327 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:94]Client received event, payload is: 2022-07-18 11:30:05.327 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]022022-07-18 11:30:05.327 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]032022-07-18 11:30:05.327 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]042022-07-18 11:30:05.327 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]052022-07-18 11:30:05.327 10477-10563/com.beantechs.nativetest1 E/vsomeip-test: [Client.cpp:96]06
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
配置文件
如上是基于同一个进程中间的通讯,那么我们在车上实现的时候,肯定是基于车载以太网来通讯的,这时候我们需要配置一下,分别为客户端与服务端来新建两个配置文件为vsomeip-server.json, 与vsomeip-client.json,内容如下:
vsomeip-server.json
{ "unicast" : "172.17.6.41", "netmask": "255.255.255.0", "applications" : [ { "name" : "Server", "id" : "0x1000" } ], "services" : [ { "service" : "0x0001", "instance" : "0x0001", "unreliable" : "30509" } ], "routing" : "Server", "service-discovery" : { "enable" : "true", "multicast" : "239.192.255.251", "port" : "30490", "protocol" : "udp", "initial_delay_min" : "10", "initial_delay_max" : "100", "repetitions_base_delay" : "200", "repetitions_max" : "3", "ttl" : "3", "cyclic_offer_delay" : "2000", "request_response_delay" : "1500" }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
vsomeip-client.json
{ "unicast" : "172.17.6.95", "netmask": "255.255.255.0", "applications" : [ { "name" : "Client", "id" : "0x1001" } ], "routing" : "Client", "service-discovery" : { "enable" : "true", "multicast" : "239.192.255.251", "port" : "30490", "protocol" : "udp", "initial_delay_min" : "10", "initial_delay_max" : "100", "repetitions_base_delay" : "200", "repetitions_max" : "3", "ttl" : "3", "cyclic_offer_delay" : "2000", "request_response_delay" : "1500" }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
然后需要配置分别为客户端来配置route host,与配置文件的路径,通过如下三个属性值来定义:
VSOMEIP_BASE_PATH : 这个从源码中来看是指定unix进程间使用Unix域套接字来实现通信的文件路径。VSOMEIP_APPLICATION_NAME : vsomeip应用的名称,跟json文件中的application对应,启动的时候会根据这个内容去找IDVSOMEIP_CONFIGURATION : 指定配置文件所在路径
- 1
- 2
- 3
在kotlin中,我们通过如下方式设置
Os.setenv("VSOMEIP_CONFIGURATION", "${cacheDir.path}/vsomeip-client.json", true) Os.setenv("VSOMEIP_BASE_PATH", "${cacheDir.path}/", true) Os.setenv("VSOMEIP_APPLICATION_NAME", "Client", true)
- 1
- 2
- 3
这样一套完整的Demo做下来,基本上对vsomeip的API应用,已经有了一定的了解,但是在实际过程中,我们觉得用的还是不得劲,如果有一种方式,能够像android中的hidl与aidl文件一样,自动生成通讯代码,不用自己去一个byte的对,那该多好呢? 其实还真的有,那就是Common API库,也是genvi组织实现的,下一篇我们来慢慢聊下