(三) 搞定SOME/IP通信之CommonAPI库

这篇具有很好参考价值的文章主要介绍了(三) 搞定SOME/IP通信之CommonAPI库。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本章主要介绍在SOME/IP通信过程中的另外一个IPC通信利剑,CommonAPI库,文章将从如下几个角度让读者了解什么是CommonAPI, 以及库在实际工作中的作用

文中资源:vsomeip+commonapi+指导文档与demo源码

CommonAPI库是什么

CommonAPI是GENIVI组织开发的一个基于C++的应用API库,没错,跟vsomeip协议栈是一个爹。其主要提供给使用通讯中间件传输数据的分布式应用来操作通讯中间件的接口。主要的作用是使使用CommonAPI进行IPC通信的的应用能够隔离底层协议栈的差异。比如使用CommonAPI时,我们的底层协议栈可以是vsomeip,也可以是DBUS等. 他的架构如下:
(三) 搞定SOME/IP通信之CommonAPI库,安卓车载系统SOME/IP通信实战,commonapi,CommonAPI,someip,SOME/IP,vsomeip
从图中可以看到,CommonAPI C++ 框架分为两个主要部分:

CommonAPI Core: 这部分与中间件无关,包含了跨不同中间件技术共享的基本 API、类和组件。它提供了构建应用程序所需的基本通信机制和抽象,而不与特定的中间件协议绑定。

CommonAPI Binding: 这部分与特定中间件相关,并包含了每种支持的中间件协议的实现细节。

通过将Core与Binding分开,CommonAPI C++ 允许开发人员使用与中间件无关的核心编写他们的应用程序逻辑,使其代码更具可移植性,不会紧密绑定到特定的中间件。然后,他们可以选择特定的绑定,将他们的应用程序适配到所需的中间件技术,而无需重写整个应用程序逻辑。

这种关注点分离使得开发更容易,可以在具有不同中间件要求的各种汽车系统中部署应用程序。它通过在中间件无关逻辑和特定中间件实现细节之间提供明确的分离,促进了可重用性和模块化。

图右边的四个框架,分别代表了Core层的代码生成工具,以及接口描述语言(fidl), Binding层的代码生成工具,以及接口描述语言(fdepl),即:

Code Generator Tools  <-->   *.fidl
Code Generator Binding Tools <--> *.fdepl

关于fidl跟fdepl文件是什么,如果你做过android开发,那么对aidl文件以及hidl文件会比较熟悉,这个fidl跟fdepl文件也是跟aidl&hidl的作用类似,我们将通信行为的接口以及参数定义在文件中,通过CommonAPI提供的Code Generators,即可将这些文件转成对应的C++接口。上层在在进行IPC接口时,只需要调用这些C++中的接口即可

CommonAPI库的编译

因为我们是基于android系统来使用CommonAPI通信,故使用ndk+gradle来编译库

编译环境

操作系统:win11
Gradle: 7.3.3
cmake版本:3.18.1

下载源码
这里包含两部分,一个是CommonAPI Core,一个是CommonAPI Binding分别对应如下两个库:

capicxx-core-runtime
capicxx-someip-runtime

下载完成后,将文件夹拷贝到上一篇文章提供的附件工程中的external目录下面,放好后如下所示:
(三) 搞定SOME/IP通信之CommonAPI库,安卓车载系统SOME/IP通信实战,commonapi,CommonAPI,someip,SOME/IP,vsomeip

修改CMakeList
然后我们需要修改工程根目录下的CMakeLists.txt文件, 注意是工程根目录,不是模块根目录,修改后内容如下所示:

cmake_minimum_required(VERSION 3.10)

project(SOMEIP)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/output/${ANDROID_ABI})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/output/${ANDROID_ABI})
set(FETCHCONTENT_SOURCE_DIR_BOOST ${CMAKE_CURRENT_SOURCE_DIR}/external/boost_1_71_0)
add_subdirectory(external/boost-cmake)
add_subdirectory(external/vsomeip)
add_subdirectory(external/capicxx-core-runtime-master)
add_subdirectory(external/capicxx-someip-runtime-master)
add_subdirectory(app/src/main/cpp)

external/capicxx-core-runtime-master/CMakeLists.txt

#添加编译标记,不然会编译报错(-Wno-ignored-attributes -Wno-deprecated-declarations)
IF(MSVC)
    message("using MSVC Compiler")
    add_definitions(-DCOMMONAPI_INTERNAL_COMPILATION -DCOMMONAPI_DLL_COMPILATION)
    add_compile_options(/EHsc /wd4996)
ELSE ()
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wformat -Wformat-security -Wconversion -fexceptions -fstrict-aliasing -fstack-protector -fasynchronous-unwind-tables -fno-omit-frame-pointer -Werror -DCOMMONAPI_INTERNAL_COMPILATION -fvisibility=hidden -Wno-ignored-attributes -Wno-deprecated-declarations")
ENDIF(MSVC)

external/capicxx-core-runtime-master/CMakeLists.txt

if ("${USE_INSTALLED_COMMONAPI}" STREQUAL "ON")
    FIND_PACKAGE(CommonAPI 3.2.0 REQUIRED CONFIG NO_CMAKE_PACKAGE_REGISTRY)
else()
# 注释掉REQUIRED
#    FIND_PACKAGE(CommonAPI 3.2.0 REQUIRED CONFIG NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH)
	FIND_PACKAGE(CommonAPI 3.2.0)
endif()

# maintainer-clean target去掉
if(NOT ANDROID)
add_custom_target(maintainer-clean COMMAND rm -rf *)
endif()

在根目录的cmake文件夹下再按照cmake的find_package规则添加两个文件,FindCommonAPI.cmake, 跟FindCommonAPI-SomeIP.cmake 两个文件

然后启动编译,就可以在工程根目录的output目录下看到库基本已经全部输出了
(三) 搞定SOME/IP通信之CommonAPI库,安卓车载系统SOME/IP通信实战,commonapi,CommonAPI,someip,SOME/IP,vsomeip

写个Demo实战一下

上面库编译完成了,书接上回的vsomeip demo,我们需要将someip_server跟someip_client这两个库改造以下,不直接使用vsomeip协议栈的API, 改为CommonAPI的方式来实现。

在写代码之前,咱们来回顾一下之前使用vsomeip协议栈API写的例子,我们定义了一个天气服务,然后服务中提供了一个获取温度的方法,参数如下:

//服务ID
static vsomeip::service_t  weather_service_id = 0x1001;
//服务实例ID
static vsomeip::instance_t weather_service_instance_id = 0x0001;
//方法ID
static vsomeip::method_t   weather_get_temp_method_id = 0x0001;

这里我们把它改造成CommonAPI的方式,首先在cpp目录下创建如下两个文件,并填入内容:

IWeatherService.fidl

package com.commapi.test

interface IWeatherService {
    version { major 0 minor 1 }

    method getTemp {
        out {
            Int32 temp
        }
    }
}

IWeatherService.fdepl

import "platform:/plugin/org.genivi.commonapi.someip/deployment/CommonAPI-4-SOMEIP_deployment_spec.fdepl"
import "IWeatherService.fidl"

define org.genivi.commonapi.someip.deployment for interface com.commapi.test.IWeatherService {
    SomeIpServiceID = 4097 //0x1001

    method getTemp {
        SomeIpMethodID = 1 //0x0001
        SomeIpReliable = true
    }
}

define org.genivi.commonapi.someip.deployment for provider as Service {
    instance com.commapi.test.IWeatherService {
        InstanceId = "com.commapi.test.IWeatherService"
        SomeIpInstanceID = 1 //0x0001
    }
}

我们这里只展示使用方式,fidl&fdepl的语法,我们后面会专门起文章来介绍。

写好后,需要下载如下两个工具:

commonapi_core_generator-3.2.0
commonapi_someip_generator-3.2.0.1

在cmd窗口,跳转到我们的fidl & fdepl文件所在目录,然后输入如下命令,即可:

commonapi-core-generator-windows-x86_64.exe -sk  *.fidl
commonapi-someip-generator-windows-x86_64.exe  *.fdepl

(三) 搞定SOME/IP通信之CommonAPI库,安卓车载系统SOME/IP通信实战,commonapi,CommonAPI,someip,SOME/IP,vsomeip
这里我们会发现我们的fidl文件夹下多了自动生成了一个src-gen的文件夹,内容如下:
(三) 搞定SOME/IP通信之CommonAPI库,安卓车载系统SOME/IP通信实战,commonapi,CommonAPI,someip,SOME/IP,vsomeip
接下来改造server端跟client端,第一步先把cpp跟.h文件加入到编译源文件中, 修改cpp目录下的CMakeLists.txt如下:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.18.1)

# Declares and names the project.
project("someip")

find_package (vsomeip3 3.3.8 REQUIRED)
find_library(log-lib log)
include_directories(${VSOMEIP3_INCLUDE_DIRS})

# CommonAPI
find_package(CommonAPI 3.2.0 REQUIRED)
include_directories(${COMMONAPI_INCLUDE_DIRS})

# CommonAPI-SomeIP
find_package(CommonAPI-SomeIP 3.2.0 REQUIRED)
include_directories(${CommonAPI-SomeIP_INCLUDE_DIRS})

# SRC-GEN
include_directories(fidl/src-gen)
file(GLOB SRC-GEN fidl/src-gen/v0/com/commapi/test/*.cpp)

add_executable(someip_server
        # Provides a relative path to your source file(s).
        someip_server.cpp
        ${SRC-GEN})


target_link_libraries(someip_server ${log-lib} vsomeip3 vsomeip3-e2e vsomeip3-sd CommonAPI CommonAPI-SomeIP)

add_executable(someip_client
        # Provides a relative path to your source file(s).
        someip_client.cpp
        ${SRC-GEN})

target_link_libraries(someip_client ${log-lib} vsomeip3 vsomeip3-e2e vsomeip3-sd CommonAPI CommonAPI-SomeIP)

编译文件修改完成后,再将我们之前的vsomeip的两个端代码修改为CommonAPI方式,对应两个文件如下:

服务端实现:someip_server.cpp

#include <string>
#include <csignal>
#include <unistd.h>
#include "CommonAPI/CommonAPI.hpp"
#include "v0/com/commapi/test/IWeatherServiceStubDefault.hpp"

using namespace v0::com::commapi::test;

class WeatherServiceStub : public IWeatherServiceStubDefault {
private:
    int temp = -32;
public:
    WeatherServiceStub() = default;
     ~WeatherServiceStub() override = default;
    void getTemp(const std::shared_ptr<CommonAPI::ClientId> _client, getTempReply_t _reply) override{
        printf("%s : gid[%d], uid[%d]\n", __func__ , _client->getGid(), _client->getUid());
        _reply(temp++);
    }
};

int main(int args, char** argc){
    //设置配置文件路径
    setenv("COMMONAPI_CONFIG", "vendor/etc/commonapi.ini",1);
    setenv("VSOMEIP_CONFIGURATION", "/vendor/etc/local_server.json", 1);
    auto runtime = CommonAPI::Runtime::get();
    auto weather_service = std::make_shared<WeatherServiceStub>();
    auto server_register = runtime->registerService("local",
                                           "com.commapi.test.IWeatherService",
                                           weather_service,
                                           "someip_server");
    printf("register weather service : %d\n", server_register);
    while(true){
        usleep(1000 * 1000);
    }
    return 1;
}

客户端实现:someip_client.cpp

#include <string>
#include <csignal>
#include <unistd.h>
#include "thread"
#include "CommonAPI/CommonAPI.hpp"
#include "v0/com/commapi/test/IWeatherService.hpp"
#include "v0/com/commapi/test/IWeatherServiceProxy.hpp"

using namespace v0::com::commapi::test;

int main(int args, char** argc){
    setenv("COMMONAPI_CONFIG", "vendor/etc/commonapi.ini",1);
    setenv("VSOMEIP_CONFIGURATION", "/vendor/etc/local_client.json", 1);
    auto runtime = CommonAPI::Runtime::get();
    auto app = runtime->buildProxy<IWeatherServiceProxy>("local",
                                                         "com.commapi.test.IWeatherService",
                                                         "someip_client");
    while(true){
        if(!app->isAvailable()){
            printf("connecting failed, retry\n");
            sleep(1);
            continue;
        }
        break;
    }
    app->getProxyStatusEvent().subscribe([&app](CommonAPI::AvailabilityStatus status){
        if(status == CommonAPI::AvailabilityStatus::AVAILABLE){
            printf("service available\n");
            std::thread t1([&app]{
                for(int i=0; i<10; i++){
                    CommonAPI::CallStatus callStatus;
                    int32_t temp;
                    CommonAPI::CallInfo callInfo;
                    app->getTemp(callStatus, temp, &callInfo);
                    printf("CallStatus = %d, getTemp: %d\n",callStatus, temp);
                }
            });
            t1.detach();
        }
    });

    while(true){
        usleep(1000 * 1000);
    }
    return 1;
}

我这里为了方便仅测试单机模式(双机模式一样的,只是配置不一样)
修改服务端配置local_server.json

{
    "unicast":"127.0.0.1",
    "logging":
    {
        "level":"debug",
        "console":"true"
    },

    "applications":
    [
        {
            "name":"someip_server",
            "id":"0x1000"
        }
    ],
    "services" :
    [
        {
            "service" : "0x1001",
            "instance" : "0x0001",
            "reliable" : { "port" : "30509", "enable-magic-cookies" : "false" }
        }
    ],
    "routing":"someip_server",
    "service-discovery" :
    {
        "enable" : "true",
        "multicast" : "239.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"
    }
}

修改客户端配置:local_client.json

{
    "unicast":"127.0.0.1",
    "netmask" : "255.255.255.0",
    "logging":
    {
        "level":"debug",
        "console":"true"
    },

    "applications":
    [
        {
            "name":"someip_client",
            "id":"0x1001"
        }
    ],
    "clients" :
    [
        {
            "service" : "0x1001",
            "instance" : "0x0001",
            "reliable" : [ "41234" ]
        }
    ],
    "service-discovery" :
    {
        "enable" : "false"
    }
}

然后按照上一篇vsomeip的方式,把库跟文件分别push到系统对应的目录,执行后,即可看到通信正常执行了,如下图。
(三) 搞定SOME/IP通信之CommonAPI库,安卓车载系统SOME/IP通信实战,commonapi,CommonAPI,someip,SOME/IP,vsomeip文章来源地址https://www.toymoban.com/news/detail-715854.html

到了这里,关于(三) 搞定SOME/IP通信之CommonAPI库的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SOME/IP 详解系列(3)—— 通信方式

    前面的文章给大家介绍了SOME/IP的功能、标准和报文格式,接下来我们开始介绍更多和实际应用相关的内容。首先,是通信方式。看看SOME/IP是如何通信的,节点之间是如何通过SOME/IP进行交互的。 在SOME/IP中,一共有三种通信方式,分别是Method、Event和Field。 Method有两种类型,

    2024年04月23日
    浏览(31)
  • 如何实现CAN-SOME/IP通信路由测试

    区别于基于UDP的车内通信路由,基于SOME/IP协议的路由增加了服务发现(Service Discovery)和服务发布(Service Publish),那对于测试工程师来说,怎么实现CAN-SOME/IP路由的测试呢? 01  认识路由实现方式 首先要了解基于SOME/IP协议的路由设计原则,如果功能实现在Ethernet节点,则

    2024年02月16日
    浏览(39)
  • <c++开发>通信工具 -之-SOME/IP移植部署 第一篇文章

    SOME/IP (Scalable service-Oriented MiddlewarE over IP) 是一种通信协议,主要用于嵌入式系统和车载网络中的服务导向通信。SOME/IP是AUTOSAR(AUTomotive Open System ARchitecture,汽车开放系统架构)标准的一部分,AUTOSAR是由主要汽车制造商和供应商共同制定的开放式汽车电子架构标准。 SOME/IP协

    2024年02月11日
    浏览(88)
  • 第二节-安卓多屏双屏实战车载车机智能驾驶舱开发/千里马android framwork开发

    hi,粉丝朋友们! 上一节已经对车载的多屏互动进行了相关的技术方案介绍,以及相关的核心方法 moveRootTaskToDisplay的讲解和使用。 具体可以参考链接:https://blog.csdn.net/learnframework/article/details/130461689 本节就来进行代码实战 要实现双屏互动,主要就只需要两个步骤: 1、手指动

    2024年02月09日
    浏览(48)
  • 让SOME/IP运转起来——SOME/IP系统设计(下)之数据库开发

    上一篇我们介绍了SOME/IP矩阵的设计流程,这一篇重点介绍如何把SOME/IP矩阵顺利的交给下游软件团队进行开发。 当我们完成SOME/IP矩阵开发,下一步需要把开发完成的矩阵换成固定格式的数据库文件,方便软件团队进行开发,目前普遍使用ARXML文件。 ARXML数据库文件开发完成后

    2024年02月04日
    浏览(46)
  • android多屏触摸相关的详解方案-安卓framework开发手机车载车机系统开发课程

    直播免费视频课程地址:https://www.bilibili.com/video/BV1hN4y1R7t2/ 在做双屏相关需求开发过程中,经常会有对两个屏幕都要求可以正确触摸的场景。但是目前我们模拟器默认创建的双屏其实是没有办法进行触摸的 静态修改方案 使用命令查看display2即副屏的信息情况 adb shell dumpsys d

    2024年02月11日
    浏览(44)
  • SOME/IP协议详解[7 SOME/IP序列化]

    什么是序列化与反序列化? 序列化是指将数据结构或对象按定义的规则转换成二进制串的过程。 反序列化是指将二进制串依据相同规则重新构建成数据结构或对象的过程。 而本质就是一种编码规范。 在SOME/IP中使用序列化的目的和作用? 使数据按照固定格式进行编排成为字

    2024年02月15日
    浏览(33)
  • 叉车车载终端定制_基于MT6762安卓核心板的车载终端设备方案

    叉车车载终端是一款专为叉车车载场景设计的4英寸Android车载平板电脑。它采用了高能低耗的8核ARM架构处理器和交互开放的Android 12操作系统,算力表现强大。此外,该产品还具备丰富的Wi-Fi-5、4G LTE和蓝牙等通讯功能,可选配外部车载蘑菇天线,确保信号更广更强。另外,车

    2024年02月02日
    浏览(53)
  • SOME/IP协议详解[6 SOME/IP-TP]

    我们知道CAN-TP是用来对当总线CAN数据过大时,就需要对CAN整包数据进行分割拆包进行发送,这个时候发送方的TP层就起作用,同理对于接收方而言,也需要将分割的数据包进行组包完成整包数据的重组还原。 因此,举一反三,我们便可以知道SOME/IP-TP模块的主体功能就是为了实

    2024年01月19日
    浏览(31)
  • 【Android车载系列】第9章 车载通信-Socket实现IPC通信机制(实现仿FDBus效果)

      FDBus 基于 Socket (TCP 和 Unix domain) 之上的IPC机制, 采用 Google protobuf 做序列化和反序列化。 FDBus还支持字符串形式的名字作为server地址。通过 name server 自动为 server 分配Unix domain 地址和 TCP 端口号, 实现 client 和server 之间用服务名字寻址。 一句话描述:FDBus (Fast Distributed Bus

    2024年02月10日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包