做曖网站,厦门建设,修改自豪地采用wordpress,WordPress建站布置回顾
SomeIP/CommonAPI环境搭建可以看我上一篇博客#xff1a;Ubuntu环境下SomeIP/CommonAPI环境搭建详细步骤
什么是SomeIP
SOME/IP#xff08;Service-Oriented Middleware over IP#xff09;是一种基于IP网络的通信协议#xff0c;旨在支持汽车电子系统和嵌入式系统…回顾
SomeIP/CommonAPI环境搭建可以看我上一篇博客Ubuntu环境下SomeIP/CommonAPI环境搭建详细步骤
什么是SomeIP
SOME/IPService-Oriented Middleware over IP是一种基于IP网络的通信协议旨在支持汽车电子系统和嵌入式系统之间的通信。它属于AUTOSARAutomotive Open System Architecture标准的一部分被设计用于构建汽车电子领域的分布式系统。
SOME/IP 使用底层的 Socket套接字机制来进行通信。SOME/IP的消息是通过UDP或TCP协议传输的
什么是CommonAPI
CommonAPI 是一种用于实现分布式服务的通用框架旨在促使不同模块或组件之间的通信更加容易。它是一种跨平台的通信框架适用于嵌入式系统、汽车电子等领域。
我们可以将 CommonAPI 视为一种接口规范CommonAPI 实际上包括两个层面的概念
1、CommonAPI 接口规范IDL CommonAPI 提供了一种接口定义语言IDL用于描述服务接口的结构包括服务的方法、属性、事件等。这种 IDL 类似于 FIDLFranca Interface Definition Language用于规范化描述接口。
2、CommonAPI 运行时环境 CommonAPI 还提供了一个运行时环境负责实际的服务注册、发现、通信等功能。这个运行时环境是 CommonAPI 框架的核心部分确保不同的组件可以协同工作实现松耦合的通信。 • CommonAPI C is divided up in a middleware-independent part (CommonAPI Core) and in a middleware-specific part(CommonAPI Binding). • CommonAPI uses the interface description language FrancaIDL for the specification of interfaces (logical interface specifica-tion). Code generation from FrancaIDL is an integrated part of CommonAPI. • The code generator for CommonAPI C bindings needs middleware-specific parameters (deployment parameters). These parameters are defined in Franca deployment files (*.fdepl). SomeIP/CommonAPI
我们可以这样理解 CommonAPI是一套接口规范通.fidl文件定义接口使用CommonAPI Core Runtime代码生成工具来解析fidl文件获得接口文件即(.cpp和.hpp)
someIP是一个利用Socket套接字机制的协议库。
我们通过解析fidl文件获得接口文件并没有IPC通讯功能为了实现其IPC通讯引入了fdepl部署文件。
fdepl根据.fidl中的接口设置每个接口的网络服务ID、网络地址、端口号、通信协议等。然后通过CommonAPI SomeIP Runtime代码生成工具解析fdepl文件生成可以通过someIP协议通信的接口文件(.cpp和.hpp)。
记要
本文参考sampleE02Attributes
接口的生成
CommonAPI其使用的接口语言为Franca IDL 语言规范。
什么是Franca? Franca 是一个用于定义和转换软件接口的框架。它用于集成来自不同供应商的基于各种运行时框架、平台和IPC进程间通信机制构建的软件组件。 Franca背景简述 接口是任何类型的软件架构中的重要工件。它们代表组件、子系统或系统之间以及组织单位如团队、部门或公司之间的合同。因此在许多开发环境中使用接口定义语言简称IDL将接口建模为一流实体。然而对于构建大型平台或系统现有的IDL至少存在两个缺点 1、为了集成来自不同来源的软件系统有必要将一个 IDL 中定义的接口映射到使用另一个 IDL 的软件模型。例如在国际 GENIVI 联盟中 正在通过集成各种开源项目、公司和机构提供的软件组件如 GENIVI 本身来开发汽车/信息娱乐系统平台。这些构建块的接口要么根本没有建模例如纯 C 或 C 标头要么以几种方法之一正式建模其中包括 UML、D-Bus Introspection XML、带注释的 Java API。模型级别上所有贡献的集成只能通过在所有这些 IDL 之间建立映射来完成。 2、大多数现有 IDL 方法的另一个常见缺点是接口动态建模缺乏正式性。大多数 IDL 提供了对接口的静态方面例如数据类型、信号、方法、属性进行建模的方法而不是动态方面例如接口上允许的事件序列动态方面通常被视为可选的附加组件到静态接口定义。 然而复杂软件系统中的许多严重错误是由接口动态方面的不匹配引起的。这些错误尤其会在项目后期阶段系统集成期间甚至客户交付后发生难以识别且修复成本高昂。因此动态方面有必要成为原始接口定义的一部分从而允许对接口的实现和使用进行广泛的形式验证。这可以通过静态分析或在运行时完成。 为了解决这两个问题GENIVI 启动了 Franca 项目该项目可以作为 IDL 转换的中心并允许将动态行为规范作为每个建模接口的组成部分。Franca 的一部分是技术和平台中立的 IDL。Franca 最初由Harman贡献 并于 2012 年 3 月在 EclipseLabs 上发布 根据 Eclipse Public License 1.0。 Franca目前的应用
Franca 自 2012 年 3 月起就是一个开源项目。因此无法提供完整的应用程序列表。不过我们将列出一些示例以展示 Franca 社区的一部分
1、GENIVI 联盟将 Franca 用作 IDL 和集成工具.
2、CommonAPI C 项目使用 Franca 模型作为所有代码生成器的起点。
3、Joynr基于 Web 的通信框架使用 Franca 作为 IDL 及其 Java 和 C 代码生成器的基础。开源 Joynr 框架支持部署在消费设备、车辆或后端基础设施上的应用程序的交互。
4、Yamaica 项目是一个 Eclipse IDE 扩展为处理 Franca 模型提供了方便的 UI 。
5、多家公司包括非汽车公司正在使用或评估 Franca 作为其内部软件平台的 IDL。 ----说还是车企用的多hhhhhh
Franca IDL详细介绍可以参考以下链接 Franca的GitHubhttps://github.com/franca/franca eclipse给出的说明https://www.eclipse.org/proposals/modeling.franca/ Franca官方文档下载download
fidl .fidl文件 这是一个接口定义文件 (Franca Interface Definition Language) 的扩展用于描述 CommonAPI 接口。它定义了服务接口相关的数据结构。这里使用E02Attributes例子中的fidl来解释。
E02Attributes.fidl
package commonapi.examplesinterface E02Attributes {version { major 1 minor 0 }attribute Int32 xattribute CommonTypes.a1Struct a1
}typeCollection CommonTypes {version { major 1 minor 0 }struct a1Struct {String sa2Struct a2}struct a2Struct {Int32 aBoolean bDouble d}
}类别诠释package组织和命名空间化接口定义的关键字interface用于声明一个接口version版本号同命名空间有关必须包含attribute通常用于定义读取和写入的属性typeCollection定义自定义的数据类型集合struct类似C中的结构体
下面我们看一下fidl(Franca Interface Definition Language)的基本类型.
基本类型对应C类型UInt8uint8_tInt8int8_tUInt16uint16_tInt16int16_tUInt32uint32_tInt32int32_tUInt64uint64_tInt64int64_tInteger整数属性这个我也没搞明白啥意思BooleanboolFloatfloatDoubledoubleStringstd::stringByteBufferstd::vectoruint8_t
全部类型详细解释可参阅Franca官方文档中5. Franca IDL Reference章节
上述我们已经大概对fidl有了基础的了解下面我们详细解释一下E02Attributes.fidl
package commonapi.examples通俗点的说就是我们定义的这些接口都在commonapi.examples命名空间下。 生成的C结构如下
namespace commonapi
{namespace examples{//接口代码在其中}
}version { major 1 minor 0 }使用version说明了这个接口版本主版本是1,次版本是0。生成的C结构如下
namespace V1
{namespace commonapi{namespace examples{//接口代码在其中}}}interface E02Attributes {version { major 1 minor 0 }attribute Int32 xattribute CommonTypes.a1Struct a1
}使用interface定义了一个接口E02Attributes这个接口通过attribute修饰了两个属性x和a1。attribute就表示我们可以通过set或get方法来设置和获取这两个属性。
第一个属性x的数据类型为Int32类型。
typeCollection CommonTypes {version { major 1 minor 0 }struct a1Struct {String sa2Struct a2}struct a2Struct {Int32 aBoolean bDouble d}
}使用typeCollection定义了一个数据集合CommonTypes这个集合里面有俩结构体。这就很简单明了和C/C一样就不赘述了。
第二个属性 a1类型为struct类型。
整个E02Attributes.fidl就表述完成了那么这个.fidl文件主要做什么呢
简单通俗的说就是定义了一个接口E02Attributes这个接口有两个属性x和a1。我们可以通过接口生成的接口文件中的get方法或者set方法来获取/设置这俩属性。
上述对E02Attributes.fidl解释就完成了。下面我们使用Ubuntu环境下SomeIP/CommonAPI环境搭建详细步骤中下载的CommonAPI Core Runtime代码生成工具 commonapi_core_generator解析fidl文件生成接口文件。
./commonapi_core_generator/commonapi-core-generator-linux-x86_64 -sk ./fidl/E02Attributes.fidl解析完成会在当前目录下生成src-gen文件夹。
./src-gen/
└── v1└── commonapi└── examples├── CommonTypes.hpp├── E02Attributes.hpp├── E02AttributesProxyBase.hpp├── E02AttributesProxy.hpp├── E02AttributesStubDefault.hpp└── E02AttributesStub.hpp3 directories, 6 files生成后我们先放着后面在说使用。下面我们要了解.fdepl文件
fdepl .fdepl 文件 重述一下fdepl 文件通常是 CommonAPI 的部署描述文件用于配置和定义 CommonAPI 服务的运行时参数以及服务的部署信息。这个文件通常包含了与服务的实际运行有关的配置信息例如服务的ID、网络地址、端口号、通信协议等。
下面我们看一下和E02Attributes.fidl适配的E02Attributes-SomeIP.fdepl文件。
E02Attributes-SomeIP.fdepl
import platform:/plugin/org.genivi.commonapi.someip/deployment/CommonAPI-4-SOMEIP_deployment_spec.fdepl
import E02Attributes.fidldefine org.genivi.commonapi.someip.deployment for interface commonapi.examples.E02Attributes {SomeIpServiceID 4660attribute x {SomeIpGetterID 3000SomeIpSetterID 3001SomeIpNotifierID 33010SomeIpNotifierEventGroups { 33010 }SomeIpAttributeReliable true}attribute a1 {SomeIpGetterID 3002SomeIpSetterID 3003SomeIpNotifierID 33011SomeIpNotifierEventGroups { 33011 }SomeIpAttributeReliable true}
}define org.genivi.commonapi.someip.deployment for typeCollection commonapi.examples.CommonTypes {struct a1Struct {}struct a2Struct {}}define org.genivi.commonapi.someip.deployment for provider as Service {instance commonapi.examples.E02Attributes {InstanceId commonapi.examples.AttributesSomeIpInstanceID 22136SomeIpUnicastAddress 192.168.0.2SomeIpReliableUnicastPort 30499SomeIpUnreliableUnicastPort 30500}
}注意fdepl我也不是很熟悉我尽力诠释
import platform:/plugin/org.genivi.commonapi.someip/deployment/CommonAPI-4-SOMEIP_deployment_spec.fdepl第一行导入了 CommonAPI 中 SOME/IP 协议相关的一些规范。
import E02Attributes.fidl导入了FIDL 文件即 E02Attributes.fidl。
define org.genivi.commonapi.someip.deployment for interface commonapi.examples.E02Attributes
{}定义了一个 CommonAPI SOME/IP 部署规范针对接口 commonapi.examples.E02Attributes
SomeIpServiceID 4660定了服务的唯一标识符Service ID即 4660。在 SOME/IP 中这是服务在网络中的唯一标识。
具体来说SomeIpServiceID 是一个整数值通常在范围 0x0001 到 0xFFFE 之间。每个服务都应该有一个不同的 ID以确保在网络中不会发生冲突。这个 ID 会随着服务的注册而分配给服务并在网络中广播使得其他节点可以识别它。 attribute x {SomeIpGetterID 3000SomeIpSetterID 3001SomeIpNotifierID 33010SomeIpNotifierEventGroups { 33010 }SomeIpAttributeReliable true}这部分配置是针对接口中的属性 x 的一些设置特别是针对 SOME/IP 协议的相关设置。让我逐项解释
SomeIpGetterID 3000 指定了属性 x 的 Getter 方法的 ID。当其他节点希望获取这个属性的值时会使用这个 ID 进行请求。
SomeIpSetterID 3001 指定了属性 x 的 Setter 方法的 ID。当其他节点希望设置这个属性的值时会使用这个 ID 进行请求。
SomeIpNotifierID 33010 指定了属性 x 的 Notifier通知器的 ID。通知器用于在属性值发生变化时通知其他节点。
SomeIpNotifierEventGroups { 33010 } 指定了 Notifier 所属的 Event Groups。Event Groups 用于在通知时进行分组这里的设置表示 Notifier 属于 Event Group 33010。
SomeIpAttributeReliable true 表示对属性 x 进行通信时要求可靠性。这意味着在进行属性值的读取和写入时要使用可靠的通信方式以确保数据的正确传输。
这些设置确保了在 SOME/IP 协议中对属性 x 的读取、写入和通知等操作有明确的标识和规范以便其他节点能够正确地进行与该属性相关的通信。
注意 Setter 操作 当有节点调用 Setter 方法设置了属性 x 的新值时如果设置成功属性的值会更新。
Notifier 发送通知 如果设置操作导致属性值发生变化系统会使用指定的 Notifier ID 向订阅了该属性变化的其他节点发送通知。
Getter 操作 在任何时候其他节点都可以使用相应的 Getter 方法来获取属性 x 的当前值。这并不要求在属性值发生变化后才能获取而是可以随时获取当前的属性值。 attribute a1 {SomeIpGetterID 3002SomeIpSetterID 3003SomeIpNotifierID 33011SomeIpNotifierEventGroups { 33011 }SomeIpAttributeReliable true}属性a1解释同属性x
define org.genivi.commonapi.someip.deployment for typeCollection commonapi.examples.CommonTypes {struct a1Struct {}struct a2Struct {}}这部分的配置是为类型集合 commonapi.examples.CommonTypes 中的结构体定义 SOME/IP 部署规范.
因为CommonTypes只是一个类型集合不是一个方法。因此不需要设置ID等属性。
define org.genivi.commonapi.someip.deployment for provider as Service {instance commonapi.examples.E02Attributes {InstanceId commonapi.examples.AttributesSomeIpInstanceID 22136SomeIpUnicastAddress 192.168.0.2SomeIpReliableUnicastPort 30499SomeIpUnreliableUnicastPort 30500}
}这部分我们依次解释
define org.genivi.commonapi.someip.deployment for provider as Service
{}这一行的配置指定了服务提供者的 SOME/IP 部署规范为提供服务的实体进行了配置 provider as Service 这表明接下来的配置是为服务提供者定义的它将提供某项服务。
instance commonapi.examples.E02Attributes
{}instance commonapi.examples.E02Attributes 这一行指定了服务提供者的服务实例即服务的具体实现。在这里服务实例的类型是 commonapi.examples.E02Attributes。
InstanceId commonapi.examples.AttributesInstanceId “commonapi.examples.Attributes” 指定了服务实例的唯一标识符即实例ID。这是服务在网络中的唯一标识。
SomeIpInstanceID 22136SomeIpInstanceID 22136 指定了服务实例在 SOME/IP 协议中的唯一标识符即实例的 SOME/IP 实例ID。在网络中通过这个ID来唯一标识服务。
SomeIpUnicastAddress 192.168.0.2SomeIpUnicastAddress “192.168.0.2” 指定了服务的网络地址即服务提供者在网络中的 IP 地址。
SomeIpReliableUnicastPort 30499SomeIpReliableUnicastPort 30499 指定了服务提供者使用的可靠单播端口号。可靠单播用于确保通信的可靠性即保证消息的完整传递。
SomeIpUnreliableUnicastPort 30500SomeIpUnreliableUnicastPort 30500 指定了服务提供者使用的不可靠单播端口号。不可靠单播通常用于一些对通信可靠性要求较低的情况。
这些配置项共同定义了服务提供者的运行时参数包括服务实例的唯一标识、网络地址、端口号等信息。这些参数确保了服务能够在网络中被正确注册、定位和访问。
下面我们使用CommonAPI SomeIP Runtime代码生成工具解析E02Attributes-SomeIP.fdepl文件。
./commonapi_someip_generator/commonapi-someip-generator-linux-x86_64 -ll verbose ./fidl/E02Attributes-SomeIP.fdepl解析完成会在当前目录下生成如下接口文件
./src-gen/
└── v1└── commonapi└── examples├── CommonTypesSomeIPDeployment.cpp├── CommonTypesSomeIPDeployment.hpp├── E02AttributesSomeIPCatalog.json├── E02AttributesSomeIPDeployment.cpp├── E02AttributesSomeIPDeployment.hpp├── E02AttributesSomeIPProxy.cpp├── E02AttributesSomeIPProxy.hpp├── E02AttributesSomeIPStubAdapter.cpp└── E02AttributesSomeIPStubAdapter.hpp3 directories, 9 files接口文件分析
我们解析完fidl文件和fdepl文件后当前目录下的src-gen目录中文件结构如下
./src-gen/
└── v1└── commonapi└── examples├── CommonTypes.hpp├── CommonTypesSomeIPDeployment.cpp├── CommonTypesSomeIPDeployment.hpp├── E02Attributes.hpp├── E02AttributesProxyBase.hpp├── E02AttributesProxy.hpp├── E02AttributesSomeIPCatalog.json├── E02AttributesSomeIPDeployment.cpp├── E02AttributesSomeIPDeployment.hpp├── E02AttributesSomeIPProxy.cpp├── E02AttributesSomeIPProxy.hpp├── E02AttributesSomeIPStubAdapter.cpp├── E02AttributesSomeIPStubAdapter.hpp├── E02AttributesStubDefault.hpp└── E02AttributesStub.hpp3 directories, 15 files*.fdepl文件生成的粘合代码,凡是带有SomeIP的一般都是我们不需要动的直接放到项目里面参与编译即可。 ├── CommonTypes.hpp 类型集合接口类不需要动用于客户端开发代理是一个提供方法调用的类
该方法调用将导致对服务的远程方法调用以及服务可以广播的事件的注册方法。
├── E02Attributes.hpp
├── E02AttributesProxyBase.hpp
├── E02AttributesProxy.hpp服务器开发存根是服务的一部分当来自客户端的远程方法调用到达时
存根将被调用它还包含将事件广播激发到几个或所有客户端的方法。├── E02AttributesStubDefault.hpp
└── E02AttributesStub.hpp阅读接口我们可以发现E02Attributes和E02AttributesProxyBase是E02AttributesProxy的父类 E02AttributesStub是E02AttributesStubDefault的父类。这样我们是不是可以认为有以下关系。
服务器端以xxxxStubDefault为父类重写接口
客户端 以xxxProxy为父类重写接口。代码演示
服务端 E02AttributesStubImpl.h
#ifndef E02ATTRIBUTESSTUBIMPL_HPP_
#define E02ATTRIBUTESSTUBIMPL_HPP_#include CommonAPI/CommonAPI.hpp
#include v1/commonapi/examples/E02AttributesStubDefault.hppclass E02AttributesStubImpl: public v1_0::commonapi::examples::E02AttributesStubDefault {public:E02AttributesStubImpl();virtual ~E02AttributesStubImpl();virtual void incCounter();private:int cnt;
};#endif // E02ATTRIBUTESSTUBIMPL_HPP_E02AttributesStubImpl.cpp
#include E02AttributesStubImpl.hppE02AttributesStubImpl::E02AttributesStubImpl() {cnt 0;
}E02AttributesStubImpl::~E02AttributesStubImpl() {
}void E02AttributesStubImpl::incCounter() {cnt;setXAttribute((int32_t)cnt);std::cout New counter value cnt ! std::endl;
}可以看到sample重写了E02AttributesStubDefault类封装了incCounter函数来更改属性X的数值。
E02AttributesService.cpp
#include thread
#include iostream#include CommonAPI/CommonAPI.hpp
#include E02AttributesStubImpl.hppint main() {CommonAPI::Runtime::setProperty(LogContext, E02S);CommonAPI::Runtime::setProperty(LogApplication, E02S);CommonAPI::Runtime::setProperty(LibraryBase, E02Attributes);std::shared_ptrCommonAPI::Runtime runtime CommonAPI::Runtime::get();std::string domain local;std::string instance commonapi.examples.Attributes;std::string connection service-sample;std::shared_ptrE02AttributesStubImpl myService std::make_sharedE02AttributesStubImpl();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));}std::cout Successfully Registered Service! std::endl;while (true) {myService-incCounter(); // Change value of attribute, see stub implementationstd::cout Waiting for calls... (Abort with CTRLC) std::endl;std::this_thread::sleep_for(std::chrono::seconds(2));}return 0;
}服务端写的比较简单首先获取运行环境
std::shared_ptrCommonAPI::Runtime runtime CommonAPI::Runtime::get();然后注册service std::string domain local;std::string instance commonapi.examples.Attributes;std::string connection service-sample;std::shared_ptrE02AttributesStubImpl myService std::make_sharedE02AttributesStubImpl();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));}std::cout Successfully Registered Service! std::endl;然后循环设置属性X的数值 while (true) {myService-incCounter(); // Change value of attribute, see stub implementationstd::cout Waiting for calls... (Abort with CTRLC) std::endl;std::this_thread::sleep_for(std::chrono::seconds(2));}官方sample写的太抽象了我们精简一下。我对服务端做了如下修改 E02AttributesStubImpl.cpp
#include E02AttributesStubImpl.hppE02AttributesStubImpl::E02AttributesStubImpl() {cnt 0;
}E02AttributesStubImpl::~E02AttributesStubImpl() {
}void E02AttributesStubImpl::incCounter() {cnt;setXAttribute((int32_t)cnt);std::cout server set X : New counter value cnt ! std::endl;std::string s_string getA1Attribute().getS();std::cout Rev S val s_string std::endl;}E02AttributesService.cpp 修改如下
#include thread
#include iostream#include CommonAPI/CommonAPI.hpp
#include E02AttributesStubImpl.hpp
#include v1/commonapi/examples/CommonTypes.hppint main() {CommonAPI::Runtime::setProperty(LogContext, E02S);CommonAPI::Runtime::setProperty(LogApplication, E02S);CommonAPI::Runtime::setProperty(LibraryBase, E02Attributes);std::shared_ptrCommonAPI::Runtime runtime CommonAPI::Runtime::get();std::string domain local;std::string instance commonapi.examples.Attributes;std::string connection service-sample;std::shared_ptrE02AttributesStubImpl myService std::make_sharedE02AttributesStubImpl();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));}std::cout Successfully Registered Service! std::endl;v1::commonapi::examples::CommonTypes::a1Struct valueStruct;valueStruct.setS(abc);v1::commonapi::examples::CommonTypes::a2Struct a2Struct valueStruct.getA2();a2Struct.setA(123);a2Struct.setB(true);a2Struct.setD(1234);valueStruct.setA2(a2Struct);int i 0;while (true) {i;myService-incCounter();if(i10){myService-setA1Attribute(valueStruct);}std::this_thread::sleep_for(std::chrono::seconds(2));}return 0;
}客户端 E02AttributesClient.cpp
#include iostream
#include thread#ifndef _WIN32
#include unistd.h
#endif#include CommonAPI/CommonAPI.hpp
#include CommonAPI/AttributeCacheExtension.hpp
#include v1/commonapi/examples/E02AttributesProxy.hppusing namespace v1::commonapi::examples;int main() {CommonAPI::Runtime::setProperty(LogContext, E02C);CommonAPI::Runtime::setProperty(LogApplication, E02C);CommonAPI::Runtime::setProperty(LibraryBase, E02Attributes);std::shared_ptr CommonAPI::Runtime runtime CommonAPI::Runtime::get();std::string domain local;std::string instance commonapi.examples.Attributes; std::string connection client-sample;//auto myProxy runtime-buildProxyWithDefaultAttributeExtensionE02AttributesProxy, CommonAPI::Extensions::AttributeCacheExtension(domain, instance, connection);auto myProxy runtime-buildProxyE02AttributesProxy(domain,instance,connection);std::cout Waiting for service to become available. std::endl;while (!myProxy-isAvailable()){std::this_thread::sleep_for(std::chrono::microseconds(10));}// Subscribe for receiving valuesmyProxy-getXAttribute().getChangedEvent().subscribe([](const int32_t val){std::cout Received change message: val std::endl;});myProxy-getA1Attribute().getChangedEvent().subscribe([](const CommonTypes::a1Struct val){std::cout Received change message for A1 std::endl;std::cout a1Struct.s val.getS()std::endl;std::cout a1Struct.a1.a2.a val.getA2().getA()std::endl;std::cout a1Struct.a1.a2.b val.getA2().getB()std::endl;std::cout a1Struct.a1.a2.d val.getA2().getD()std::endl;});while (true){std::this_thread::sleep_for(std::chrono::microseconds(1000000));}
}这就不需要解释了对照着service分析客户端就 “见码知意” 了。
如果想要在client端修改属性可参考下面代码 // Asynchronous call to set attribute of servicestd::functionvoid(const CommonAPI::CallStatus, int32_t) fcb recv_cb;myProxy-getXAttribute().setValueAsync(value, fcb, info);// Asynchronous call to set attribute of type structure in serviceCommonTypes::a1Struct valueStruct;valueStruct.setS(abc);CommonTypes::a2Struct a2Struct valueStruct.getA2();a2Struct.setA(123);a2Struct.setB(true);a2Struct.setD(1234);valueStruct.setA2(a2Struct);std::functionvoid(const CommonAPI::CallStatus, CommonTypes::a1Struct) fcb_s recv_cb_s;myProxy-getA1Attribute().setValueAsync(valueStruct, fcb_s, info);运行
service刚启动时 client刚启动时 service启动10s后 client启10s后
结语
SomeIP/CommonAPI这个系列我会坚持更下去本文只粗浅的使用了一下更多内容后续会出教程(二)
如需要源码资料可联系QQ918619587
如有错误感谢指正。
禁止转载