vsomeip部署在Linux
  BPI26WEjHJmG 2023年11月02日 41 0


1.环境准备

  • Ubuntu 18.04.6 LTS
  • c++编译器
  • 编译用的cmake
  • 相关的库
sudo apt-get install libboost-system1.55-dev libboost-thread1.55-dev libboost-log1.55-dev
sudo apt-get install source-highlight doxygen graphviz
sudo apt-get --no-install-recommends install asciidoc

2.源码下载

git clone https://github.com/COVESA/vsomeip.git

3.源码编译

cd vsomeip
$ mkdir build
$ cd build
$ cmake -DENABLE_SIGNAL_HANDLING=1 ..
$ make
$ make install

具体可以参照源码当中的REAMD文件

vsomeip部署在Linux_车载通信

vsomeip部署在Linux_Someip部署_02

vsomeip部署在Linux_车载通信_03

安装相关的vsomeip头文件和依赖库.so

vsomeip部署在Linux_自动驾驶_04

4.创建相关测试文件

4.1 创建server 测试文件

  • 创建一个someip-example文件目录
  • 在里面添加一个sevice_example.cpp文件添加
#include <vsomeip/vsomeip.hpp>


std::shared_ptr<vsomeip::application> app;

int main()
{
    app = vsomeip::runtime::get()->create_application("world");

    app->init();

    app->start();

    return 0;
}

简单代码

  • 在sevice_example.cpp同目录下添加一个CMakeLists.txt文件
  • 编写CMakeLists.txt编译选项内容如下
cmake_minimum_required (VERSION 3.10.2)

project (vSomeIPServiceExample)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

find_package(Threads REQUIRED)

include_directories("/usr/local/include/")
link_directories("/usr/local/lib")

include_directories(${VSOMEIP_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIR})

find_package(vsomeip3 REQUIRED)

add_executable(service-example ../sevice_example.cpp)
target_link_libraries(service-example vsomeip3 pthread)
  • 执行make 编译可执行程序service-example

vsomeip部署在Linux_自动驾驶_05

4.2 创建client 测试文件

  • 添加测试源文件client_example.cpp
  • 添加cmake内容编译client_example源文件

vsomeip部署在Linux_网络_06

  • 执行make编译可执行程序

vsomeip部署在Linux_自动驾驶_07

4.3 执行程序

  • server端启动

vsomeip部署在Linux_车载通信_08

  • client端启动

vsomeip部署在Linux_客户端_09

  • server接收到client端连接

vsomeip部署在Linux_客户端_10

4.4 提供Request/Response 功能

  • server添加代码
#include <iomanip>
#include <iostream>
#include <sstream>
#include <vsomeip/vsomeip.hpp>

#define SAMPLE_SERVICE_ID 0x1234
#define SAMPLE_INSTANCE_ID 0x5678
#define SAMPLE_METHOD_ID 0x0421

 

std::shared_ptr<vsomeip::application> app;

 
void on_message(const std::shared_ptr<vsomeip::message> &_request) {

    std::shared_ptr<vsomeip::payload> 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);

}

 

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();

    return 0;

}

服务端提供 message_handler 和 offer 功能。

register_message_handler函数在 someip/application.hpp 中的定义描述为:

virtual void register_message_handler(service_t _service,
instance_t _instance, method_t _method,
message_handler_t _handler) = 0;
//为指定的 method 或 event 注册处理程序。用户应用程序必须调用此方法来为其注册回调。
//每个服务(SERVICE)、实例(INSTANCE)、方法/事件(METHOD)组合只能注册一个处理程序。

offer_service函数在 \vsomeip-master\interface\vsomeip\application.hpp 中的定义描述为:

virtual void offer_service(service_t _service, instance_t _instance,
major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor =
DEFAULT_MINOR) = 0;

//参数 _service:service标识符;
//参数 _instance:提供的服务实例的实例标识符;
//参数 _major:主服务版本号(默认为0);
//参数 _minor:次服务版本号(默认为0)。

offer_service 函数的作用是将service 注册到 vsomeip 路由组件上,从而使感兴趣的客户端可以看到该服务,因此用户应用程序必须为它提供的每个 service 调用offer_service这个方法。根据配置,service有两种模式,一种是只能在内部网络中可用的,另一种是在内部和外部均可使用。为了向外部网络提供服务, 配置中必须包含提供服务实例的端口,如果没有提供这样的端口配置,服务在设备外部是不可见的。

  • client添加代码
#include <iomanip>
#include <iostream>
#include <sstream> 
#include <condition_variable>
#include <thread>
#include <vsomeip/vsomeip.hpp>

 

#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<std::mutex> 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);

}

 

void on_message(const std::shared_ptr<vsomeip::message> &_response) {

    std::shared_ptr<vsomeip::payload> its_payload = _response->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 << "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();

}

与服务端的代码一样,在客户端代码中我们也需要调用 register_message_handler 注册一个消息处理程序,用来接收服务器对客户端请求的响应。原则上,创建请求消息非常容易。只需通过调用 create_request() 获取请求对象,设置 service ID、instance ID 和 method ID,并在最后将序列化的数据写入payload。在上面这个示例中,我们将 0 到 9 的值写入有效负载(std::vector< vsomeip::byte_t >)。

上述代码中出现 “std::thread sender(run);” 的原因是:当我们尝试将请求从客户端发送给服务时,遇到了一个小问题。在发送消息之前必须启动应用程序(app->start()),因为我们需要一个正在运行的事件循环来处理消息。但是该方法 app->start() 不会返回,因为它内部有正在运行的事件循环。因此,就需要启动一个线程(run),并在此线程中等待 availability 回调的返回,然后再调用app->send(request)。

vsomeip部署在Linux_Someip部署_11

vsomeip部署在Linux_客户端_12


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  LxKByvFwtHdi   2023年11月02日   51   0   0 客户端CSShtml
BPI26WEjHJmG
作者其他文章 更多