动态后端系统
功能
现代汽车系统非常复杂,通常需要在严格的时间内开发。因此,新的系统应该有效地重用以前开发的系统的一部分。同时,主要开发由独立公司(一级供应商)完成。为了能够重用以前项目的代码,并整合一级供应商的代码,API被分为两层:前端和后端。在Qt IVI中,前端API被称为功能,因为通常一个特定的类负责一个特定的功能区域,例如QIviClimateControl,它控制气候功能区域。
后端
为了正确运行,每个功能都需要与其连接的一个后端。这个后端必须实现相应的功能后端接口。只有这样,你才能在功能和其后端之间建立一个有效的连接。
通常,每个功能只有一个后端接口类,后端需要为该功能实现。每个后端接口都从QIviFeatureInterface派生,它提供了每个功能所需的通用函数和信号,例如错误处理。
后端实现组合在一起,并在一个Qt插件中实现。这使得同时提供多个后端并在运行时切换后端变得容易。这些后端插件通过QtIviCore加载。一个插件可以提供多个功能的后端实现,无需为每个功能创建单独的插件。
Qt IVI还区分两种后端类型
- 生产 - 在生产系统中,您只想运行生产后端。
- 模拟 - 在开发阶段,拥有一个模拟后端可能很有用,您可以使用它进行前端开发,直到后端服务可用。
Qt IVI使用简单的命名方案来标识插件是否提供模拟或生产后端。每个模拟插件名必须包含“simulation”或“simulator”。或者,您也可以在插件的元数据中设置“simulation”键。这对于静态插件特别有用。
QtIviCore
QtIviCore模块提供所有需要将部件组合在一起的类。除了提供如QIviAbstractFeature或QIviServiceObject之类的基类之外,该模块还提供了QIviServiceManager,负责加载必要的后端插件。
QIviServiceManager
QIviServiceManager 是 QtIviCore 的核心部分,记录所有可用的后端及其导出的接口。服务管理器扫描所有可用的插件和它们的元数据。这个过程使得它只加载需要功能的插件,以减少启动时间。所有这些信息都以模型的形式收集在服务管理器中,这使开发者能够选择他们想要使用的插件。
服务对象
服务对象概念使功能灵活,并能实时切换后端。QIviServiceObject 是一个句柄,功能用来连接到正确的后端接口。这个句柄提供了查询后端接口的可用性、由服务对象实现的方法。服务对象自动包装在插件中,这使得多个功能共享服务对象,并显式选择为功能实例使用哪个后端。
根据上面的图示,服务对象是特定插件的句柄。《功能A》和《功能B》都使用相同的服务对象,为《功能A》返回 Feature_A_Interface 实例,为《功能B》返回 Feature_B_Interface 实例。功能类继承自 QIviAbstractFeature;后端接口继承自 QIviFeatureInterface。
代理服务对象
与代表后端插件句柄的正常 QIviServiceObject 相比,QIviProxyServiceObject 不需要插件即可工作。它可以在应用程序端初始化,并用任何继承自 QIviFeatureInterface 的类填充。QIviProxyServiceObject 在某些场景中很有用,尤其是当不需要在单独的插件中实现功能的后端实现时,而是在应用程序的代码库中实现。
代理服务对象也用于其他功能的属性模型。有关更多详细信息,请参阅模型。
功能如何找到其后端
通常,所有功能都使用自动发现模式。从 QML,你可以在 QIviAbstractFeature::discoveryMode 属性中设置;从 C++,你可以使用 QIviAbstractFeature::startAutoDiscovery() 启动它。该属性要求 QIviServiceManager 提供所有可用的后端,这些后端实现了您功能所需的接口。然后,管理器选择第一个匹配的后端并将功能连接到它。《QIviAbstractFeature》总是首先请求生产后端;如果没有任何可用的,它将回退到模拟后端。此行为可以通过 QIviAbstractFeature::discoveryMode 控制使用,默认为 QIviAbstractFeature::AutoDiscovery。可以通过 QIviAbstractFeature::discoveryResult 提取结果的会话列表风格类型,在功能成功加载后端之后,《QIviAbstractFeature::serviceObject》属性将保持加载的 ServiceObject,而《QIviAbstractFeature::isValid》返回 true
。
详细的连接顺序
根据上述气候控制的例子,连接顺序将如下
- 在 QML 中创建一个 ClimateControl 元素。
- ClimateControl 在完成时调用了 QIviAbstractFeature::startAutoDiscovery。
- QIviAbstractFeature::startAutoDiscovery 询问 QIviServiceManager 所有的后端服务。
- QIviServiceManager 搜索所有可用的插件及其实现的接口;这个搜索只进行一次。
- QIviAbstractFeature 接受第一个 QIviServiceObject 并连接到相应的接口。
- ClimateControl 元素已经准备好使用。
手动分配
如果您不希望您的功能使用自动发现机制,请将 discoveryMode 设置为 QIviAbstractFeature::NoAutoDiscovery。之后,该特性将不再搜索后端,并且您需要手动分配一个 ServiceObject。
发现模式
对于像气候控制系统这样的特性,自动发现机制非常适用,因为通常一个特性和提供一个实现该特性的后端之间存在1:1的映射。对于像媒体播放器这样的更通用接口,这可能就不够了:您可以控制内置的媒体播放器后端,但您可能还想通过蓝牙控制手机上的媒体播放器。
为了实现这一点,首先,您需要发现可用的设备,然后将所选设备的 ServiceObject 传递给媒体播放器接口。可用手机的秘密可以通过 DiscoveryModel 完成。这为您提供了每个找到的设备的服务对象。发现模型的概念不仅限于手机,它可用于所有未直接连接到系统的后端,如互联网服务或控制多个后排系统。
分区域功能
区域是一种标准方式,用于为车辆中的多个点提供单一的API。例如,气候控制系统通常有驾驶员区域和乘客区域;甚至还有一个后排区域。相同的概念适用于方向盘、车门、后视镜、窗户等。
常用的模式是结合区域与属性属性,以处理区域之间能力的微小差异;例如,汽车的乘客侧没有方向盘加热功能。
从技术上讲,区域功能由同一功能的多个实例组成,一个顶层实例提供独立于区域的API和对特定区域实例的访问。该特性需要从 QIviAbstractZonedFeature 派生并实现 createZoneFeature() 以提供特定于区域的实例。
顶层接口可以提供车辆级的设置。例如,是否在气候控制系统API中使用再循环。相反,区域接口提供每个区域的函数,如所需温度。
构建区域特性需要后端接口从 QIviZonedFeatureInterface 派生。这个类为后端提供了一个接口来列举可用的区域。此接口还包括必要的 QIviZonedFeatureInterface::initialize 方法来初始化任何属性。
©2020 The Qt Company Ltd. 本文档中包含的贡献文档版权归各自的所有者所有。此处提供的文档是在自由软件基金会发布的《GNU自由文档许可证》第1.3版下许可使用的。GNU自由文档许可证。Qt和相关标志是The Qt Company Ltd.在芬兰以及其他国家和地区注册的商标。所有其他商标均为各自所有者的财产。