aboutsummaryrefslogtreecommitdiffstats
path: root/src/ivicore/doc/src/backend-system.qdoc
blob: c933a2a10e2cbe2e29d017160c38791cfda6e893 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Copyright (C) 2019 Luxoft Sweden AB
** Copyright (C) 2018 Pelagicore AG
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\page backend-system.html
\title Dynamic Backend System
\nextpage Models
\contentspage Concepts

\section1 Feature

Modern automotive systems are very complex, usually developed on a strict timeframe. Consequently,
it is efficient to reuse parts of previously developed systems, for a new system. At the same time,
the main development is done by independent companies (tier-1). To make it possible to reuse code
from previous projects, and also incorportae code from tier-1 partners, the APIs are split into two
layers: a frontend and a backend. In Qt IVI, the frontend API is called a \b feature, as usually a
specific class is responsible for a specific feature area, such as QIviClimateControl, which
controls the climate feature area.

\section1 Backend

To function correctly, every feature needs to have a backend connected to it. This backend must
implement a corresponding feature backend interface. Only then, you can create a valid connection
between the feature and its backend.

Usually, every feature has only one backend interface class, which the backend needs to implement
for the feature to work. Every backend interface is derived from QIviFeatureInterface, which
provides generic functions and signals that every feature needs, such as error handling.

The backend implementations are grouped together and implemented inside a
\l{How to Create Qt Plugins}{Qt plugin}. This makes it easy to provide multiple backends
simultaneously and switch the backend at runtime. These backend plugins are loaded through
\l{QtIviCore}. A plugin can provide backend implementations for multiple features; there is no
need to create a separate plugin for each feature.

Qt IVI also distinguishes between two types of backends:

\list
    \li \b{production} - On a production system, you want to have only production backends running.
    \li \b{simulation} - During the development phase, it may be useful to have a simulation
        backend that you can use for frontend development, until the backend services are usable.
\endlist

Qt IVI uses a simple naming scheme to identify whether a plugin provides simulation or production
backends. Every simulation plugin needs to have either "simulation" or "simulator" in its name.
Alternatively, you can also set the "simulation" key in the plugin's metadata. This is especially
useful for static plugins.

\image backend-types.png "Types of Backend"

\section1 QtIviCore

The QtIviCore module provides all the classes that are needed to glue the parts together. In
addition to providing the base classes like QIviAbstractFeature or QIviServiceObject, this module
also provides the QIviServiceManager, responsible for loading the necessary backend plugins.

\image feature-backend.png "Relationship between the Feature and the Backend"

\section2 QIviServiceManager

The QIviServiceManager is the central part of QtIviCore, keeping a record of all the available
backends and their exported interfaces. The service manager scans through all available plugins and
their accompanying metadata. This process gives it the ability to only load plugins that a Feature
requires, to reduce the startup time. All of this information is collected in the service manager
in the form of a model, which enables developers to choose the plugin they want to use.

\section2 ServiceObjects

The ServiceObject concept keeps the features flexible, and makes it possible to switch between
backends at runtime. A QIviServiceObject is a handle, which the feature uses to connect to the
correct backend interface. This handle provides methods to query the backend interfaces available,
which the ServiceObject implements. ServiceObjects automatically wrap around plugins, making it
possible to share the ServiceObject between multiple features and to explicitly select which
backend to use for your feature instance.

\image app-service-object-backend.png "Relationship between the App and the Backend"

Based on the diagram above, the ServiceObject is the handle for a specific plugin. \b {Feature A}
and \b {Feature B} both use the same ServiceObject, which returns an instance of \b
Feature_A_Interface for \b {Feature A} and \b Feature_B_Interface for \b {Feature B}. The Feature
classes derive from QIviAbstractFeature; the backend interfaces derive from QIviFeatureInterface.

\section2 ProxyServiceObjects

In contrast to the normal QIviServiceObject, which represents a handle to a backend plugin, the
QIviProxyServiceObject doesn't need a plugin to work. It can be instantiated on the application
side and filled with any QIviFeatureInterface derived class. QIviProxyServiceObject is useful for
scenarios when a backend implementation of a feature should not be done inside a separate plugin,
but inside the application's code base itself.

\image proxy-service-objects.png "Proxy Service Objects"

ProxyServiceObjects are also used for models that are properties of another feature. For more
details, see \l{Models}.

\section1 How a Feature Finds its Backend

Typically, all Features use the auto discovery mode. From QML, you can set the
QIviAbstractFeature::discoveryMode property; from C++, you can start this with
QIviAbstractFeature::startAutoDiscovery(). This property asks the QIviServiceManager for all the
backends available, that implement the required interface for your feature. The manager then
chooses the first matching backend and connects the feature to it. QIviAbstractFeature always
asks for production backends first; if none are available, it falls back to a simulation backend.
This behavior can be controlled using the QIviAbstractFeature::discoveryMode, that defaults to
QIviAbstractFeature::AutoDiscovery. The resulting backend type can be retrieved via
QIviAbstractFeature::discoveryResult. After the feature has loaded a backend successfully, the
QIviAbstractFeature::serviceObject property holds the loaded ServiceObject and
QIviAbstractFeature::isValid returns \c true.

\section2 Detailed Connection Order

Based on the aforementioned climate control example, the detailed connection would be as follows:

\list 1
    \li A ClimateControl element is created in QML.
    \li ClimateControl calls QIviAbstractFeature::startAutoDiscovery upon completion.
    \li QIviAbstractFeature::startAutoDiscovery queries QIviServiceManager for all backends
        available.
    \li QIviServiceManager searches for all plugins available and the interfaces they implement;
        this search is only done once.
    \li QIviAbstractFeature accepts the first QIviServiceObject and connect to the corresponding
        interface.
    \li The ClimateControl element is ready to be used.
\endlist

\section2 Manual Assignment

If you don't want your feature to use the auto discovery mechanism, set the discoveryMode to
QIviAbstractFeature::NoAutoDiscovery. After that, the feature won't search for a backend anymore,
and you need to assign a ServiceObject manually.

\section2 DiscoveryModels

For features like the climate control example, the auto discovery mechanism is fitting, as there
is usually a 1:1 mapping between a feature and a backend providing the implementation for that
feature. For more generic interfaces like a media player, this might not be sufficient: you could
control a built-in media player backend with this, but you might also want to control the media
player running on your mobile phone over bluetooth.

For this to work, first, you would need to discover the devices available and then pass the
ServiceObject of the selected device to the media player interface. The discovery of the available
mobile phones can be done using a DiscoveryModel. This provides you with a ServiceObject for each
device found. The concept of a discovery model is not limited to mobile phones, it can be used for
all backends that are not hard wired to the system, like Internet services or controlling multiple
rearseat systems.

\section1 Zoned Features

Zones are a standard way to provide a single API for multiple points in the vehicle. For instance,
climate control commonly has a driver zone and passenger zone; or even a back seat zone. The same
concept applies to wheels, doors, mirrors, windows, and more.

A common pattern is to combine zones with property attributes to handle small differences in
capabilities between zones; for example, there's no steering wheel heater in a car's passenger side.

Technically, a zoned feature consists of multiple instances of the same feature, a top-level
instance which provides the zone-independent API and access to instances for a specific zone.
The feature needs to derive from QIviAbstractZonedFeature and implement createZoneFeature() to
provide zone-specific instances.

The top-level interface can provide vehicle wide settings. For example, whether recirculation
should be used in a climate control API. In contrast, the zoned interface provides per-zone
functions, such as the desired temperature.

Building a zoned feature requires the backend interface to be derived from QIviZonedFeatureInterface.
This class provides the backend with an interface to enumerate the zones available. This interface
also includes the necessary QIviZonedFeatureInterface::initialize method to initialize any
properties.

*/