最后更新:2022-02-01 23:10:49 手机定位技术交流文章
点击返回雪云飞星的SOME/IP协议详解「总目录」
someip提供基于网络的面向服务的通信机制,而每个服务一般都是由相近或相关的一些功能组成。在someip中规定服务中可以包含三种接口,这三种接口对应了我们在
SOME/IP协议详解「1.1·面向服务与面向信号」
中讲解的事件发送、方法调用和字段处理。在someip中称为Methond、Event和Field,这里按下不表,下一段详细讲解

我们继续说明什么是服务,我们举个车载空调的例子。空调是大家生活中常见的物品,提供我们加热、制冷等功能。由于现代的空调功能越来越多,我们不做详细举例,这里仅仅说明最基本的几个功能:

那么对于有上述需求的一个空调程序,我们将其形成一个服务。通过someip给出的三种接口,就可以将上面的6种功能设计成上图中的接口形式:
需要说明的是:
其实Method|Event|Field这些都是上层的概念。上层不考虑下层通信,认为下层通信都被完美封装起来,所以上层的使用就像是在一个芯片中调用其他接口一样。真正对应到下层代码具体实现上,就是三种机制的支撑:
由1和2组成了Method概念|3组成Event概念|1、2和3组成Field概念
我们尝试用代码来理解一下这几个概念,虽然不能100%的准确描述,但是帮忙大家理解是一个很好的手段
我们将一个服务看成一个类的定义:
class AirConditionerService
服务的定义可以实例化,且可以被多实例化;此处我们实例化出一个来,且不考虑通信过程,就认为其是全局的:
AirConditionerService AirConditionerInstance
Method就是一个被调用的函数,里面可以执行各种算法,对于类来讲,就很好理解了,就正好对应类的方法。例如图中的:
注意这里的调用者是另一个ECU(ECU2),而仅通过someip将接口里的数据传输过来,ECU0收到数据后,执行响应的功能。比如此处对端想要调用OpenOrCloseMachine方法,就得对state赋值为on,然后将其传给ECU0,ECU0收到后调用OpenOrCloseMachine函数,并将state作为入参传入。OpenOrCloseMachine这个函数收到判断是否state==on,然后执行打开空调的操作,运行压缩机等等
上面的OpenOrCloseMachine只有一个boolean类型的入参,所以不具备数据返回功能,即ECU2远程调用OpenOrCloseMachine函数后就直接结束了,拿不到更多的信息,也不知道空调是否被真正打开。这种只有传入没有返回的Method被称为FF Method(Fire&Forget Method),如果想要返回状态,就要用到RR Method(Request/Response Method)。而RR的方法的函数会长成下面的样子:
这样一来,通过responseState就可以返回空调是否真的被打开了,当然也可以顺便返回一些其他数据,比如空调当前的功率、风量等等信息。有时候,如果数据类型和含义是一致的情况下,也可以做成inout的形式,即一个入参可以即传入,又返回,比如:
那么客户端可以通过inoutState传入请求的状体啊,服务端也可以通过这个参数返回当前状态,这种方式也属于RR方法
事件和Method刚好相反,是由服务端主动发送数据给客户端;而不是像Method那样,请求一次响应一次。Event什么时候发送数据都是因为服务端自己满足了某种条件
还是说空调的事,空调服务可以通过Event发送当前的环境温度给对端(比如给显示屏)。可以是周期的发送,也可以是某个事件(比如这个温度改变了才发送,或者其他什么事件都可以,由应用开发者决定就好)。由于环境温度还是基本上都是实时在变化的,所以上述图中的就是基于一个周期Task去循环发送温度;谁用谁调这个接口就可以,入参就是当前的环境温度
其实事件本身并不是用来传数据的(那是Field干的,上述传输环境温度只是帮助大家理解,并不是一个很好的实践),它本质上还是一个事件,比如空调出现了什么故障,或者切换到某种模式了都是一个事件;是用来通知对方的一种机制,甚至都可以没有参数,比如下面的:
可以和FF Method组成一个异步的关机流程:
比如ECU2调用OpenOrCloseMachine(off)去要求ECU0里的空调关机。但是关机不是立马关掉的,所以过了一分钟后,ECU0成功关闭了空调,然后通过MachineTurnOff()接口再告诉ECU2(或者别的也行)成功关机了
Field与前面两种最大的不同就是Field的核心是操控一个具体的数据,这个数据一般来说是一个具有具体意义的变量;而Method和Event最主要的作用是用来执行某些动作,虽然也具有对变量的操控能力,但是在设计的时候,最好将变量操作设计为Field,更加合理
变量的操作也就是读和写两种,分别对应getter和setter。还有一种就是notifier,也是读的一种,与event类似,不需要客户端主动读;服务端在发生了某些变动的时候,可以主动发送这个数据,或者甚至也可以周期发送。就比如博主在代码里写的一样,由于SetTargetTemperature可以被多个ECU调用(ECU1,2,3都可以),那么可以设计成当有ECU来设置这个数据的时候,就可以通知单个或者所有ECU当前的目标温度,以达到同步更新的效果(防止ECU1更新了数据,ECU2和3都还不知道)
还有需要注意的一点是:
点击返回雪云飞星的SOME/IP协议详解「总目录」
本文由 在线网速测试 整理编辑,转载请注明出处。