aboutsummaryrefslogtreecommitdiffstats
path: root/src/ivicore/doc/src/simulation-system.qdoc
blob: 63f0a360d76d82b64d89d12e8c87eda121f36c7a (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
/****************************************************************************
**
** 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 QtIvi module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL-QTAS$
** Commercial License Usage
** Licensees holding valid commercial Qt Automotive Suite 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 simulation-system.html
\title Qt IVI Simulation System
\previouspage Qt IVI Query Language

When you develop new APIs, a service that the API requires may not exist yet. This is because, the
API is already designed but the service itself is still being developed. For example, with new
concepts like Autonomous Driving, the UI interaction and its API are designed, but the Autonomous
Drive Service is not yet completed. This development cycle requires the need to separate the API
developemnt from the service. The \l{Dynamic Backend System} provides the architecture to enable
this separation.

Once we have this separation in place, the next step for devleoping the API is a way to simulate
its behavior to mirror the original service. The Qt IVI Simulation System enables the following
use cases:

\list
    \li An easy to define simulation logic in QML
    \li A flexible system to provide simulation for any C++ API
    \li A clear split between simulation data and simulation logic
    \li An override mechanism to change the simulation at runtime; useful for autotests
    \li An integration with the IVIGenerator tools
\endlist

\section1 Architecture

Since the simulation system builds on top of the \l{Dynamic Backend System}, the API split
follows the same schema:

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

Each backend plugin needs to implement the backend interface to provide the necessary functionality
to the frontend. For example, the QIviClimateControlBackendInterface class for the
QIviClimateControl frontend API.

In the backend, every call from the frontend is forwarded to QML, where we can script a simulation
behavior.

\image simulation-system.png "QtIvi Simulation System"

\section1 QML API

The core of the Qt IVI Simulation System is the QIviSimulationEngine. This engine extends
QQmlApplicationEngine and provides the extra functionality to connect C++ and QML logic together.

Each backend uses its own simulation engine to separate the frontend code from the backend QML
code. To provide a binding between QML and C++ objects, the C++ instance must be registered
with the QIviSimulationEngine under a certain name. For each registered C++ instance, the engine
creates a proxy object and exposes it as a QML type. These QML types can be used to provide the
behavior for functions or to update properties.

For example, suppose your feature has a function called \c increment() and a property called
\c counter. The actual behavior for \c increment() is implemented in the backend:

\code
void increment() {
    counter++;
}
\endcode

When we autogenerate classes, the actual bevhavior of \c increment() cannot be autogenerated,
because there's no way to tell the autogenerator the kind of behavior this function should have.
To define this behavior, you need to implement a complete backend in C++.

The QIviSimulationEngine makes this task more flexible, as it forwards all of the C++ calls to
QML, allowing you to use QML to define the behavior, via scripting. Consequently, you can override
the behavior and also script a default behavior without touching any of the C++ code.

For more information on working with the simulation engine, see \l{QIviSimulationEngine}.

\section1 Separate Data from Logic

The simulation system makes it possible to separate the simulation business logic from the
simulation data. The simulation data is stored in JSON files, for the
QIviSimulationEngine::loadSimulationData() function to load. Once the simulation data is loaded,
the IviSimulator global object provides the content to all QML simulation files.

For example, you can use the IviSimulator::findData function to read the data for a specific
interface only:

\qml
property var settings : IviSimulator.findData(IviSimulator.simulationData, "QIviClimateControl")
\endqml

\section2 Boundary Checks

The IviSimulator global object also provides functions to make boundary checks easier. The property
boundaries are defined in the JSON files, while the QML code stays generic, to work with multiple
different boundary checks:

\qml
function setAirConditioningEnabled(airConditioningEnabled) {
    if (IviSimulator.checkSettings(airConditioningEnabled, settings["airConditioningEnabled"])) {
        console.log("SIMULATION airConditioningEnabled changed to: " + airConditioningEnabled);
        backend.airConditioningEnabled = airConditioningEnabled
    } else {
        setError("SIMULATION changing airConditioningEnabled is not possible: provided: " + airConditioningEnabled + " constraint: " + IviSimulator.constraint_string(settings["airConditioningEnabled"]));
    }
}
\endqml

Use the IviSimulator::checkSettings() function to check the specified \e airConditioningEnabled
value against the boundaries defined in the JSON file. If the value is within the boundaries,
then it is updated; otherwise an error is returned together with the constraint in a human-readable
form.

For more information about simulation and the data format, see \l{IviSimulator}.

\section1 Override Mechanism

For app development or unit testing, it is often useful to trigger a certain behavior in the
backend. For example, when implementing message boxes for error recovery, the app developer may
need a way to easily trigger this exact error condition. Suppose that the simulation behavior
provided by the backend developer, for this use case, is not be sufficient.

In this case, the Qt IVI Simulation System provides an override system to load your own simulation
behavior file or data file, via an environment variable.

Each QIviSimulationEngine can have an additional identifier to override the default behavior file
or data file, using the following environment variables:

\badcode
QTIVI_SIMULATION_OVERRIDE=<identifier>=<file>[;<identifier>=<file>]
QTIVI_SIMULATION_DATA_OVERRIDE=<identifier>=<file>[;<identifier>=<file>]
\endcode

\section1 Integrate with IVIGenerator

The simulation system is already integrated into the IVIGenerator tools and it is used
automatically when generating code with the \l{Backend Simulator}{backend_simulator} format.

The autogenerated plugin uses the QFace module name as the QIviSimulationEngine identifier, to
allow overriding at runtime.

All boundary annotations defined in \l{config_simulator_default}{config_simulator} are then
transformed into a JSON file, and embedded as a resource file into the backend.

For each interface, a QML simulation file is created, providing a default implementation to
check the boundaries of each property.

\section2 Define Your Own Simulation Files

It's not always convenient to use the autogenerated QML simulation files. You can also define your
own QML file by using the \l{config_simulator_simulationFile}{simulationFile annotation}.

\note If your QFace file provides multiple interfaces, the corresponding simulation file must
provide a simulation for all of these interfaces.

To reuse the autogenerated simulation files from an existing interface as a starting point, you
can load these autogenerated simulation files using a QML import statement:

\qml
import 'qrc:/simulation/'
\endqml

Afterwards you should be able to load your modified simulation files like a regular QML file.

*/