一,关于车载软件通信
传统的车载软件通信采用的是经典的总线协议(比如CAN、LIN、FlexRay),这些总线采用的是面向信号的数据传输(Signal-based),基于信号在双绞线中的传输来通信,但是这些协议的传输带宽和传输速率有限,且不容易实现基于无线网更新车载软件(OTA)的需求。因此,新一代的车载软件通信更多采用了SOA架构下的SOME/IP协议,该协议采用的是面向服务的数据传输(Service-Oriented),基于ECU的服务在车载以太网中被请求或订阅来通信。
二,SOME/IP简介
SOME/IP是基于以太网实现的中间件通信协议。SOME/IP 是”Scalable Service-Oriented Middleware over IP”的缩写。
SOME/IP在以太网模型的分层中,位于TCP/UDP传输层以上,属于应用层。
三,SOME/IP的特点
1.支持序列化操作。作为通信节点的ECU可能有不同的软件架构或者操作系统,为了保证传输机制的一致性,SOME/IP允许将UDP/TCP报文进行序列化操作。
2.支持远程过程调用 (RPC)。客户端可以远程地向服务器端请求数据,也可以远程地在服务器端执行某些函数。
3.服务发现(SD)。在面向服务的架构中,服务必须是可发现的,SOME/IP有个单独的SD模块负责服务的实现。
4.支持发布/订阅。客户端可以订阅服务器的内容,从而可以动态地接收来自服务器的更新数据。
四,SOME/IP消息格式
SOME/IP序列化消息的数据头格式如下:
Message ID: 用来标识参与远程调用的Method或者Event
Request ID: 用来标识不同的Client对象或者同一个Client对象发起的不同Session会话
Message Type: 用来区分消息体类型
常见的消息体类型:request/response/notification/error
Return Code: 通常返回E_OK(0x00),如果返回的是Response或Error消息体类型就不会是 0x0
Payload: 参与传输的数据段
五,SOME/IP的主要通信模式
1.Request/Response Methods
客户端发送请求到服务器,以及从服务器返回响应到客户端。服务器的错误响应也会返回给客户端。
2.Fire and Forget Methods
客户端向服务器发送请求,服务端不返回响应。
3.Notification Events
客户端订阅服务器的内容,每当服务器有数据变化或执行某任务后通知给订阅过的客户端。哪些客户端需要订阅由SOME/IP-SD来管理。
4.Field
一个字段表示一个状态,订阅该字段的客户端将字段值作为初始事件。字段值后面的每次更新都会通知给客户端。
六,SD 服务发现流程
1.SD有两种机制:
第一种机制是“提供服务”,服务器可以使用它向网络提供可用服务。另一种是“查找服务”,它使客户端能够请求到可用服务。
2.服务发现具体流程:
1.服务器通过广播发布消息
2.客户端通过广播查找消息
3.客户端找到消息后,进行订阅和确认(Subscribe – Ack)
3.SD过程的工作模式:
客户端的两种模式:请求和监听(Request and Listen)
服务器端的两种模式:提供和静默(Offer and Silent)
七,常见的开源实现–基于vSomeIP
BMW基于 SOME/IP 标准实现了开源的vsomeip框架,vsomeip能够独立集成到各种操作系统。
代码样例–Request/Response模式:
服务器端:
include
include
include
include
define SAMPLE_SERVICE_ID 0x1234
define SAMPLE_INSTANCE_ID 0x5678
define SAMPLE_METHOD_ID 0x0421
std::shared_ptr app;
void on_message(const std::shared_ptr &_request) {
std::shared_ptr its_payload = _request->get_payload();
vsomeip::length_t l = its_payload->get_length();
// Get payload
std::stringstream ss;
for (vsomeip::length_t i=0; i<l; i++) {
ss << std::setw(2) << std::setfill('0') << std::hex
<< (int)*(its_payload->get_data()+i) << " ";
}
std::cout << "SERVICE: Received message with Client/Session ["
<< std::setw(4) << std::setfill('0') << std::hex << _request->get_client() << "/"
<< std::setw(4) << std::setfill('0') << std::hex << _request->get_session() << "] "
<< ss.str() << std::endl;
// Create response
std::shared_ptr<vsomeip::message> its_response = vsomeip::runtime::get()->create_response(_request);
its_payload = vsomeip::runtime::get()->create_payload();
std::vector<vsomeip::byte_t> its_payload_data;
for (int i=9; i>=0; i--) {
its_payload_data.push_back(i % 256);
}
its_payload->set_data(its_payload_data);
its_response->set_payload(its_payload);
app->send(its_response, true);
}
int main() {
app = vsomeip::runtime::get()->create_application(“World”);
app->init();
app->register_message_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID, on_message);
app->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
app->start();
}
客户端:
include
include
include
include
include
include
define SAMPLE_SERVICE_ID 0x1234
define SAMPLE_INSTANCE_ID 0x5678
define SAMPLE_METHOD_ID 0x0421
std::shared_ptr< vsomeip::application > app;
std::mutex mutex;
std::condition_variable condition;
void run() {
std::unique_lock its_lock(mutex);
condition.wait(its_lock);
std::shared_ptr< vsomeip::message > request;
request = vsomeip::runtime::get()->create_request();
request->set_service(SAMPLE_SERVICE_ID);
request->set_instance(SAMPLE_INSTANCE_ID);
request->set_method(SAMPLE_METHOD_ID);
std::shared_ptr< vsomeip::payload > its_payload = vsomeip::runtime::get()->create_payload();
std::vector< vsomeip::byte_t > its_payload_data;
for (vsomeip::byte_t i=0; i<10; i++) { its_payload_data.push_back(i % 256); } its_payload->set_data(its_payload_data);
request->set_payload(its_payload);
app->send(request, true);
}
void on_message(const std::shared_ptr &_response) {
std::shared_ptr its_payload = _response->get_payload();
vsomeip::length_t l = its_payload->get_length();
// Get payload
std::stringstream ss;
for (vsomeip::length_t i=0; iget_data()+i) << ” “;
}
std::cout << “CLIENT: Received message with Client/Session [” << std::setw(4) << std::setfill(‘0’) << std::hex << _response->get_client() << “/” << std::setw(4) << std::setfill(‘0’) << std::hex << _response->get_session() << “] “
<< ss.str() << std::endl;
}
void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) {
std::cout << “CLIENT: Service [“
<< std::setw(4) << std::setfill(‘0’) << std::hex << _service << “.” << _instance
<< “] is “
<< (_is_available ? “available.” : “NOT available.”)
<< std::endl;
condition.notify_one();
}
int main() {
app = vsomeip::runtime::get()->create_application(“Hello”);
app->init();
app->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, on_availability);
app->request_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
app->register_message_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID, on_message);
std::thread sender(run);
app->start();
}
服务器端的配置:
{
“unicast” : “172.17.0.2”,
“logging” :
{
“level” : “debug”,
“console” : “true”,
“file” : { “enable” : “false”, “path” : “/tmp/vsomeip.log” },
“dlt” : “false”
},
“applications” :
[
{
“name” : “World”,
“id” : “0x1212”
}
],
“services” :
[
{
“service” : “0x1234”,
“instance” : “0x5678”,
“unreliable” : “30509”
}
],
“routing” : “World”,
“service-discovery” :
{
“enable” : “true”,
“multicast” : “224.224.224.245”,
“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”
}
}
客户端的配置:
{
“unicast” : “172.17.0.1”,
“logging” :
{
“level” : “debug”,
“console” : “true”,
“file” : { “enable” : “false”, “path” : “/var/log/vsomeip.log” },
“dlt” : “false”
},
“applications” :
[
{
“name” : “Hello”,
“id” : “0x1313”
}
],
“routing” : “Hello”,
“service-discovery” :
{
“enable” : “true”,
“multicast” : “224.224.224.245”,
“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.https://inspiredhobbyist.org/what-is-some-ip-in-autosar/
2.https://mdnice.com/writing/6c21d60b8e74456b8d84004ced9baae2
3.https://github.com/COVESA/vsomeip/wiki/vsomeip-in-10-minutes
慢慢进步吧,waiting and hope.
声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/206813.html