CommonAPI学习笔记-1

CommonAPI学习笔记-1

一. 整体结构

在这里插入图片描述
CommonAPI分为两层:核心层和绑定层,使用了Franca来描述服务接口的定义和部署,而Franca是一个用于定义和转换接口的框架(https://franca.github.io/franca/)。

​ 核心层和通信中间件无关,使用fidl配置文件来描述接口的逻辑,绑定层和中间件相关(DBUS/SOMEIP)。因此在fdepl配置文件中设置了中间件所依赖的参数。(CommonAPI C++ is divided up in a middleware-independent part (CommonAPI Core) and in a middleware-specific part(CommonAPI Binding) )

​ 通过代码生成工具(core-generator, someip-generator和dbus-generator)根据配置文件生成核心层和绑定层的业务代码,这些业务代码依赖CommonAPI的运行库libCommonAPI.so,而CommonAPI的运行库则依赖CommonAPI的绑定库(libCommonAPI-SomeIP.so),CommonAPI的绑定库依赖具体的中间件运行时库 (libsomep.so)。
在这里插入图片描述

二. Franca 配置文件

​ 前面说过CommonAPI分为核心层和绑定层,核心层和绑定层都有代码生成工具,我们需要根据业务场景的实际需求,编写对应的fidl(核心层)和fdepl(绑定层)配置文件,并且由代码生成工具生成代码。

​ fidl文件主要由下列元素组成:

类型说明
package接口所属的名称空间,类似JAVA的包名或者DDS中的domainid
interface接口名称,相当于someip中的serviceid
version接口版本号,这个版本号同样会被绑定层使用到
attribute接口中的属性成员,对外提供读和写的接口
typeCollection用于自定义类型的容器,内部保存用户自己定义的数据类型
struct用户自定义数据类型,类似C语言的结构体

​ fidl文件的范例(来自官方代码https://github.com/COVESA/capicxx-core-tools/blob/master/CommonAPI-Examples/E02Attributes/fidl/E02Attributes.fidl):

/* Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)* This Source Code Form is subject to the terms of the Mozilla Public* License, v. 2.0. If a copy of the MPL was not distributed with this* file, You can obtain one at http://mozilla.org/MPL/2.0/. */package commonapi.examples  // package包名interface E02Attributes {    // interface接口名称version { major 1 minor 0 }   // 接口版本号attribute Int32 x      // 基本数据类型属性attribute CommonTypes.a1Struct a1  // 用户自定义数据类型属性
}typeCollection CommonTypes {    // 用户自定义类型集合version { major 1 minor 0 }  // 类型版本号struct a1Struct {     // 用户自定义类型String sa2Struct a2       // 嵌套了用户自定义类型成员}struct a2Struct {	  // 用户自定义类型Int32 aBoolean bDouble d}
}

​ fdepl文件对应的是绑定层的代码实现,因此,fdepl文件中的配置是和绑定层对应的中间件相对应的,例如如果fidl中定义了接口中的属性,那么如果绑定层是someip的话,那么fdepl文件中需要指定接口对应的someip服务的信息(serviceid, instanceid),属性对应的方法信息(method, eventid, eventgroupid)等,这里用官方范例中的fdepl文件(https://github.com/COVESA/capicxx-core-tools/blob/master/CommonAPI-Examples/E02Attributes/fidl/E02Attributes-SomeIP.fdepl)来说明

/* Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)* This Source Code Form is subject to the terms of the Mozilla Public* License, v. 2.0. If a copy of the MPL was not distributed with this* file, You can obtain one at http://mozilla.org/MPL/2.0/. */import "platform:/plugin/org.genivi.commonapi.someip/deployment/CommonAPI-4-SOMEIP_deployment_spec.fdepl"
import "E02Attributes.fidl"    // 重点,这个import就意味着如果不先生成fidl对应的代码文件,可能无法生成该fdepl文件的代码文件
// 定义了commonapi.examples.E02Attributes这个服务接口的CommonAPI SOME/IP部署规范(SOMEIP服务的参数配置)
define org.genivi.commonapi.someip.deployment for interface commonapi.examples.E02Attributes { //这里会生成部署文件/* service id = 0x1235*/SomeIpServiceID = 4661   // fidl中服务接口对应someip服务idattribute x {         // fidl的接口中,属性对应someip的属性(包含get和set方法以及notifier对应的事件和事件组)SomeIpGetterID = 3000   // somep属性的get方法 method_idSomeIpSetterID = 3001	// somep属性的set方法 method_idSomeIpNotifierID = 33010  // // somep属性的notifier对应的event_idSomeIpNotifierEventGroups = { 33010 }   // 事件组SomeIpAttributeReliable = true    // someip属性的通信方式(TCP/UDP)}attribute a1 {SomeIpGetterID = 3002SomeIpSetterID = 3003SomeIpNotifierID = 33011SomeIpNotifierEventGroups = { 33011 }SomeIpAttributeReliable = true}
}
// 只是将fidl中用户自定义类型在这里简单的申明了一下,实际测是下来是可以删除的,并不影响绑定层代码的生成和编译,删除也会生成绑定层的CommonTypes代码文件
define org.genivi.commonapi.someip.deployment for typeCollection commonapi.examples.CommonTypes {struct a1Struct {}struct a2Struct {}}
// 这部分为CommonAPI接口实例和SOME/IP服务提供者(provider)之间的关系
define org.genivi.commonapi.someip.deployment for provider as Service {   // 实例关系申明开始instance commonapi.examples.E02Attributes {     // E02Attributes接口实例1InstanceId = "commonapi.examples.Attributes"   // E02Attributes接口实例名称   SomeIpInstanceID = 22136    // someip的service instance_id    // 对应的SOMEIP服务instance_id}// 下面其实可以申明多个实例的
}    // 实例关系申明结束

三. Generate Code

  1. fidl生成的代码文件:在这里插入图片描述

  2. fdepl生成的代码文件:
    在这里插入图片描述

  3. 依赖关系:
    在这里插入图片描述
    ​ 用户应用程序是不需要关心绑定层的,用户应用程序直接和核心层配置文件生成的代码打交道,通过CommonAPI核心层的运行时Runtime创建核心层的Proxy和Stub(E02AttributesProxy,E02AttributesStub)。

​ 用户应用程序创建E02AttributesProxy和E02AttributesStub对象,这两个对象都是核心层的对象,实现了CommonAPI核心层的Proxy和Stub接口。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

​ 可以看到fidl生成出来的Proxy和Stub类都是核心层的Proxy和Stub接口的实现类。

​ 绑定层生成的Proxy和Stub类在程序开始运行的时候就将自己的构造函数注册到绑定层的工厂中,构造函数和CommonAPI的接口名进行绑定,如下:

在这里插入图片描述
在这里插入图片描述

​ INITIALIZER宏是用于展开其中的函数定义,将函数定义为跟随程序模块启动时自动加载运行,因此,INITIALIZER宏中定义的函数在程序的main函数之前就被执行了,INITIALIZER宏中会将fdepl生成的绑定层Proxy/Stub的初始化函数注册给SomeIP/DBus绑定层Factory (CommonAPI::SomeIP: : Factory),后者会在初始化的时候执行注册进来的所有绑定层Proxy/Stub的初始化函数,大致的时序如下:

在这里插入图片描述

​ 可以从上面的时序图看出来,注册给CommonAPI::SomeIP::Factory的函数(initializeHelloWorldSomeIPProxy)的用途有两个:

  1. 注册核心层interface和绑定层中间件服务之间的对应关系

    CommonAPI::SomeIP::AddressTranslator::get()->insert("local:commonapi.examples.E02Attributes:v1_0:commonapi.examples.Attributes",0x1235, 0x5678, 1, 0);    // AddressTranslator中记录了commonapi interface和Someip Service信息之间的对应关系
    
  2. 注册绑定层Proxy/Stub的创建函数

    CommonAPI::SomeIP::Factory::get()->registerProxyCreateMethod("commonapi.examples.E02Attributes:v1_0",    // CommonAPI Interface&createE02AttributesSomeIPProxy);     // 绑定层根据fdepl生成Proxy的创建函数
    
    CommonAPI::SomeIP::Factory::get()->registerStubAdapterCreateMethod("commonapi.examples.E02Attributes:v1_0",    // CommonAPI Interface&createE02AttributesSomeIPStubAdapter);     // 绑定层根据fdepl生成Stub的创建函数
    

​ 生成的核心层的Proxy和Stub代码的主要作用是根据fidl中定义的接口规范生成对应的接口客户端和服务端的接口代码,此外还有一个作用就是实现getInterface接口,这个接口会返回fidl中定义的服务的interface接口名称。创建核心层的Proxy和Stub时需要指定Common的Domain,interface接口名称和Instanceid,依据这三个参数核心层怎么知道该怎么创建绑定层的Proxy和Stub,有怎么知道绑定层的通信参数(例如service_id,instance_id)呢?

​ 这个就要依赖生成的绑定层代码在INITIALIZER宏注册的initialize函数来完成了,每个绑定层工厂中有一个map容器保存CommonAPI的interface和该绑定层通信地址的对应关系:

CommonAPI::SomeIP::AddressTranslator::get()->insert("local:commonapi.examples.E02Attributes:v1_0:commonapi.examples.Attributes",0x1235, 0x5678, 1, 0);    // AddressTranslator中记录了commonapi interface和Someip Service信息之间的对应关系CommonAPI::SomeIP::Factory::get()->registerProxyCreateMethod("commonapi.examples.E02Attributes:v1_0",    // CommonAPI Interface&createE02AttributesSomeIPProxy);     // 绑定层根据fdepl生成Proxy的创建函数

​ 核心层的createProxy/registerStub函数会将让手下目前支持的两个绑定层(DBus和SomeIP)去各自Factory中看下是否注册过这次传入的CommonAPI的interface,如果有的话就能找到对应的中间件的通信参数,创建中间件的服务实例,这部分代码逻辑在CommonAPI::Runtime::createProxyHelper中:

std::shared_ptr<Proxy>
Runtime::createProxyHelper(const std::string &_domain, const std::string &_interface, const std::string &_instance,const std::string &_connectionId, bool _useDefault) {std::lock_guard<std::mutex> itsLock(factoriesMutex_);for (auto factory : factories_) {   // 绑定层工厂容器,包括someip/dbus//如果通过AddressTranslator注册过,那么这里就能创建出绑定层的Proxystd::shared_ptr<Proxy> proxy= factory.second->createProxy(_domain, _interface, _instance, _connectionId);if (proxy)return proxy;}return (_useDefault && defaultFactory_ ?defaultFactory_->createProxy(_domain, _interface, _instance, _connectionId): nullptr);
}

​ 由于生成的Proxy代码已经在INITIALIZER中调用了registerProxyCreateMethod注册了创建绑定层Proxy的函数,因此绑定层工厂就可以找到该函数来创建绑定层Proxy,代码如下:

std::shared_ptr<CommonAPI::Proxy>    // CommonAPI-SomeIP绑定层工厂创建绑定层Proxy
Factory::createProxy(const std::string &_domain,    // CommonAPI的domainconst std::string &_interface, const std::string &_instance,    // CommonAPI的interface和instanceconst ConnectionId_t &_connectionId) {auto proxyCreateFunctionsIterator= proxyCreateFunctions_.lower_bound(_interface);if (proxyCreateFunctionsIterator!= proxyCreateFunctions_.end()) {std::string itsInterface(_interface);if (proxyCreateFunctionsIterator->first != _interface) {  // 首先根据interface找注册过的绑定层Proxy创建函数std::string itsInterfaceMajor(_interface.substr(0, _interface.find('_')));if (proxyCreateFunctionsIterator->first.find(itsInterfaceMajor) != 0)return nullptr;    //如果该Interface没有注册过绑定层创建函数,则直接返回nullptritsInterface = proxyCreateFunctionsIterator->first;}CommonAPI::Address address(_domain, itsInterface, _instance);Address someipAddress;   // 保存绑定层中间件通信的地址参数// 从AddressTranslator中找注册的绑定层Proxy的创建函数if (AddressTranslator::get()->translate(address, someipAddress)) {std::shared_ptr<Connection> itsConnection  // 这个Connection类封装了对vsomeip中间件的调用= getConnection(_connectionId);if (itsConnection) {std::shared_ptr<Proxy> proxy= proxyCreateFunctionsIterator->second(    //使用注册的prox创建函数生成fdepl中的绑定层ProxysomeipAddress, itsConnection);if (proxy && proxy->init())   // 初始化绑定层Proxyreturn proxy;}}}COMMONAPI_ERROR("Creating proxy for \"", _domain, ":", _interface, ":",_instance, "\" failed!");return nullptr;
}

四. 基本开发流程

  1. 安装vsomeip库

    https://blog.csdn.net/qq_43655213/article/details/129344035

  2. 安装commonapi代码生成工具

    https://blog.csdn.net/qq_43655213/article/details/129344035

  3. 编译并且安装commonapi代码库

    https://blog.csdn.net/qq_43655213/article/details/129344035

  4. 编写fidl和fdepl

    https://github.com/COVESA/capicxx-core-tools/blob/master/CommonAPI-Examples/E02Attributes/fidl/E02Attributes-SomeIP.fidl

    https://github.com/COVESA/capicxx-core-tools/blob/master/CommonAPI-Examples/E02Attributes/fidl/E02Attributes-SomeIP.fdepl

  5. 生成generated-code

    如下两行命令会在当前目录下创建src-gen目录并且生成核心层和绑定层的Proxy和Stub相关代码文件:

    commonapi-core-generator-linux-x86_64 -sk E02Attributes-SomeIP.fidl

    commonapi-someip-generator-linux-x86_64 -ll verbose E02Attributes-SomeIP.fdepl

  6. 编写客户端应用

    客户端:

    a. 指定创建的domain, instance, connection_name

    std::string domain = "local";
    std::string instance = "commonapi.examples.Attributes"; 
    std::string connection = "client-sample";
    

    b. 通过CommonAPI::Runtime创建Proxy

    std::shared_ptr < CommonAPI::Runtime > runtime = CommonAPI::Runtime::get();
    auto myProxy = runtime->buildProxyWithDefaultAttributeExtension<E02AttributesProxy, CommonAPI::Extensions::AttributeCacheExtension>(domain, instance, connection);
    // 等待对端stub可用
    std::cout << "Waiting for service to become available." << std::endl;
    while (!myProxy->isAvailable()) {std::this_thread::sleep_for(std::chrono::microseconds(10));
    }
    

    c. 调用Proxy中实现的fidl定义的接口

    服务端:

​ a. 指定创建的domain, instance, connection_name

std::string domain = "local";
std::string instance = "commonapi.examples.Attributes"; 
std::string connection = "service-sample";

​ b. 创建绑定层Stub对象

std::shared_ptr<E02AttributesStubImpl> myService = std::make_shared<E02AttributesStubImpl>();

​ c. 注册绑定层Stub对象到SomeIP绑定层工厂

while (!runtime->registerService(domain, instance, myService, connection)) {std::cout << "Register Service failed, trying again in 100 milliseconds..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

​ 注意:E02AttributesStubImpl是需要用户自行实现fdepl生成的绑定层Stub抽象类的接口的,fdepl生成的绑定层Stub类是个抽象类,因为毕竟只有用户才知道该怎么实现这个接口,生成工具做不到的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/8013.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单片机基础模块学习——DS18B20温度传感器芯片

不知道该往哪走的时候&#xff0c;就往前走。 一、DS18B20芯片原理图 该芯片共有三个引脚&#xff0c;分别为 GND——接地引脚DQ——数据通信引脚VDD——正电源 数据通信用到的是1-Wier协议 优点&#xff1a;占用端口少&#xff0c;电路设计方便 同时该协议要求通过上拉电阻…

Golang Gin系列-9:Gin 集成Swagger生成文档

文档一直是一项乏味的工作&#xff08;以我个人的拙见&#xff09;&#xff0c;但也是编码过程中最重要的任务之一。在本文中&#xff0c;我们将学习如何将Swagger规范与Gin框架集成。我们将实现JWT认证&#xff0c;请求体作为表单数据和JSON。这里唯一的先决条件是Gin服务器。…

< OS 有关 > 阿里云:轻量应用服务器 的使用 :轻量化 阿里云 vpm 主机

原因&#xff1a; &#xff1c; OS 有关 &#xff1e; 阿里云&#xff1a;轻量应用服务器 的使用 &#xff1a;从新开始 配置 SSH 主机名 DNS Tailscale 更新OS安装包 最主要是 清除阿里云客户端这个性能杀手-CSDN博客 防止 I/O 祸害系统 操作&#xff1a; 查看进程&#x…

设计模式的艺术-代理模式

结构性模式的名称、定义、学习难度和使用频率如下表所示&#xff1a; 1.如何理解代理模式 代理模式&#xff08;Proxy Pattern&#xff09;&#xff1a;给某一个对象提供一个代理&#xff0c;并由代理对象控制对原对象的引用。代理模式是一种对象结构型模式。 代理模式类型较多…

K8S极简教程(4小时快速学会)

1. K8S 概览 1.1 K8S 是什么 K8S官网文档&#xff1a;https://kubernetes.io/zh/docs/home/ 1.2 K8S核心特性 服务发现与负载均衡&#xff1a;无需修改你的应用程序即可使用陌生的服务发现机制。存储编排&#xff1a;自动挂载所选存储系统&#xff0c;包括本地存储。Secret和…

python3+TensorFlow 2.x(五)CNN

目录 CNN理解 code实现人脸识别 数据集准备&#xff1a; code实现 模型解析 结果展示 结果探讨 基于vgg16的以图搜图 数据准备 图库database 检索测试集datatest code实现 code解析 结果展示 CNN理解 卷积神经网络&#xff08;CNN&#xff09;是深度学习中最强大…

(一)HTTP协议 :请求与响应

前言 爬虫需要基础知识&#xff0c;HTTP协议只是个开始&#xff0c;除此之外还有很多&#xff0c;我们慢慢来记录。 今天的HTTP协议&#xff0c;会有助于我们更好的了解网络。 一、什么是HTTP协议 &#xff08;1&#xff09;定义 HTTP&#xff08;超文本传输协议&#xff…

FPGA实现任意角度视频旋转(完结)视频任意角度旋转实现

本文主要介绍如何基于FPGA实现视频的任意角度旋转&#xff0c;关于视频180度实时旋转、90/270度视频无裁剪旋转&#xff0c;请见本专栏前面的文章&#xff0c;旋转效果示意图如下&#xff1a; 为了实时对比旋转效果&#xff0c;采用分屏显示进行处理&#xff0c;左边代表旋转…

如何移植ftp服务器到arm板子?

很多厂家提供的sdk&#xff0c;一般都不自带ftp服务器功能&#xff0c; 需要要发人员自己移植ftp服务器程序。 本文手把手教大家如何移植ftp server到arm板子。 环境 sdk&#xff1a;复旦微 Buildroot 2018.02.31. 解压 $ mkdir ~/vsftpd $ cp vsftpd-3.0.2.tar.gz ~/vs…

【阅读笔记】基于整数+分数微分的清晰度评价算子

本文介绍的是一种新的清晰度评价算子&#xff0c;整数微分算子分数微分算子 一、概述 目前在数字图像清晰度评价函数中常用的评价函数包括三类&#xff1a;灰度梯度评价函数、频域函数和统计学函数&#xff0c;其中灰度梯度评价函数具有计算简单&#xff0c;评价效果好等优点…

LabVIEW 保存文件 生产者/消费者设计

LabVIEW 保存文件 生产者/消费者设计 简介生产消费模式设计结构 简介 主从模式的数据通信是利用全局变量、局域变量或共享变量实现的&#xff0c;由于这些变量的每次复制都是原始数据的一个副本&#xff0c;占据了大量的空间。实际上&#xff0c;只需要使用一部分缓冲区作为数…

网络安全 | F5-Attack Signatures-Set详解

关注&#xff1a;CodingTechWork 创建和分配攻击签名集 可以通过两种方式创建攻击签名集&#xff1a;使用过滤器或手动选择要包含的签名。  基于过滤器的签名集仅基于在签名过滤器中定义的标准。基于过滤器的签名集的优点在于&#xff0c;可以专注于定义用户感兴趣的攻击签名…

宏_wps_宏修改word中所有excel表格的格式_设置字体对齐格式_删除空行等

需求&#xff1a; 将word中所有excel表格的格式进行统一化&#xff0c;修改其中的数字类型为“宋体&#xff0c; 五号&#xff0c;右对齐&#xff0c; 不加粗&#xff0c;不倾斜”&#xff0c;其中的中文为“宋体&#xff0c; 五号&#xff0c; 不加粗&#xff0c;不倾斜” 数…

项目集成RabbitMQ

文章目录 1.common-rabbitmq-starter1.创建common-rabbitmq-starter2.pom.xml3.自动配置1.RabbitMQAutoConfiguration.java2.spring.factories 2.测试使用1.创建common-rabbitmq-starter-demo2.目录结构3.pom.xml4.application.yml5.TestConfig.java 配置交换机和队列6.TestCon…

Shotcut新版来袭,新增HSL滤镜、硬件编码,剪辑更流畅

Shotcut 是一款功能强大、完全免费且开源的多平台视频编辑工具&#xff0c;适用于 Windows、macOS 和 Linux 系统。作为一款专业的视频编辑软件&#xff0c;它不仅支持数百种音频和视频格式的直接编辑&#xff0c;还提供了无需导入即可进行原生编辑的便捷功能。Shotcut 的核心优…

K8s运维管理平台 - xkube体验:功能较多

目录 简介Lic安装1、需要手动安装MySQL&#xff0c;**建库**2、启动命令3、[ERROR] GetNodeMetric Fail:the server is currently unable to handle the request (get nodes.metrics.k8s.io qfusion-1) 使用总结优点优化 补充1&#xff1a;layui、layuimini和beego的详细介绍1.…

BAHD酰基转移酶对紫草素的手性催化-文献精读105

Two BAHD Acyltransferases Catalyze the Last Step in the Shikonin/Alkannin Biosynthetic Pathway 两个BAHD酰基转移酶催化了紫草素/左旋紫草素生物合成途径中的最后一步 一个BAHD酰基转移酶专门催化紫草素的酰基化&#xff0c;而另一个BAHD酰基转移酶则仅催化紫草素的对映…

STM32完全学习——RT-thread在STM32F407上移植

一、写在前面 关于源码的下载&#xff0c;以及在KEIL工程里面添加操作系统的源代码&#xff0c;这里就不再赘述了。需要注意的是RT-thread默认里面是会使用串口的&#xff0c;因此需要额外的进行串口的初始化&#xff0c;有些人可能会问&#xff0c;为什么不直接使用CubMAX直接…

单片机内存管理剖析

一、概述 在单片机系统中&#xff0c;内存资源通常是有限的&#xff0c;因此高效的内存管理至关重要。合理地分配和使用内存可以提高系统的性能和稳定性&#xff0c;避免内存泄漏和碎片化问题。单片机的内存主要包括程序存储器&#xff08;如 Flash&#xff09;和数据存储器&a…

“AI质量评估系统:智能守护,让品质无忧

嘿&#xff0c;各位小伙伴们&#xff01;今天咱们来聊聊一个在现代社会中越来越重要的角色——AI质量评估系统。你知道吗&#xff1f;在这个快速发展的时代&#xff0c;产品质量已经成为企业生存和发展的关键。而AI质量评估系统&#xff0c;就像是我们的智能守护神&#xff0c;…