OTX-Runtime for DotNet
|
|
The runtime behavior of the communication channels (ComChannel) and the associated diagnostic services (DiagService) is handled inside the OTX-DiagManager API. It is described in detail in this chapter. The description is aimed at system integrators who need precise knowledge of the behavior. Especially when the DiagManager is used by several applications at the same time.
Note: The DiagManager manages the communication channels and diagnostic services automatically!
Note: ISO 13209-3 deliberately leaves room for implementation in the runtime behavior of a
ComChannel
and aDiagService
. This freedom is precisely specified here.
A ComChannel represents a LogicalLink
(MCDLogicalLink
in case of a MVCI-Server) to an ECU or a FunctionalGroup
, see Functional Addressing. It can be used for communication. A LogicalLink
is defined in a VehicleInformation
of the ODX data base.
A DiagService represents a MCDDiagComPrimitive
(MCDDiagComPrimitive
in case of a MVCI-Server) of an MCDLogicalLink
. It contains request and response parameters and can be executed synchronously or asynchronously to the ECU.
In addition, the following diagnostic runtime system-specific topics influence the runtime behavior and should therefore be considered:
A ComChannel can be created in the following different ways:
Note: Inside the DiagManager a ComChannel is assigned to a
LogicalLink
. MultipleComChannel
instances, which can be also inside multiple DiagManager clients, can be assigned to the sameLogicalLink
. Inside the DiagManager eachLogicalLink
has oneCommandThread
. Each command inside theCommandThread
will be executed command by command.
Syntax:
The term GetComChannel creates a ComChannel for the passed combination of identifier
and ecuVariantName
. If the current variant is to be identified, communication with the ECU is also started and the ECU variant is identified and selected. The following pseudo-code describes the simplified behavior.
Note: Perform-Variant-Selection (PVS) practically means that the
BaseVariant
orEcuVariant
is generated first and then a special diagnosis service is called. The ComChannel can then change its selected variant.
Syntax:
The term CreateComChannel creates a ComChannel for the passed combination of identifier
and ecuVariantName
.
Note: The behavior is the same as GetComChannel with
performVariantSelection
=
false
.
Note: The
ComChannel
will be only created. No communication with the ECU was started.
Syntax:
The term GetComChannelFromComInterface creates a ComChannel for the passed combination of identifier
and ecuVariantName
at he given ComInterface. If the current variant is to be identified, communication with the ECU is also started and the ECU variant is identified and selected.
Note: The behavior is the same as with GetComChannel, except that the given interface is used.
Syntax:
The term CreateComChannelFromComInterface creates a ComChannel for the passed combination of identifier
and ecuVariantName
at he given ComInterface.
Note: The behavior is the same as with CreateComChannel, except that the given interface is used.
A communication channel can be created implicitly or explicitly. With implicit creation, the communication channel is created within another term and is therefore not assigned to an explicit ComChannel declaration. In the following example, the DiagService is generated implicitly with the term CreateDiagServiceByName to send a diagnostic service via ExecuteDiagService. This in turn generates the necessary ComChannel
implicitly via GetComChannel.
Both DiagService and ComChannel only exist temporarily as they are not assigned to any declaration. When it is created explicitly, the communication channel is assigned to a ComChannel
declaration, which can then be used further, see example:
Created DiagService objects are not cached. In contrast to this, created ComChannel objects are always cached, see ComChannel Lifetime - Caching. This means that an implicitly created ComChannel
is not deleted or closed in DiagManager
. This must be done explicitly, see ComChannel Lifetime - Closing.
Note: No matter how many times the same ComChannel is created explicitly or implicitly and not closed, it always returns the same
ComChannel
. But the content of thisComChannel
can be different, see table in Subsequent ComChannel Creation.
Important: Creating a DiagService, explicitly or implicitly, always creates a new instance. Since this has an impact on memory and performance, only the necessary instances should be created for memory and performance-critical applications.
An opened ComChannel will be closed immediately in the following cases:
Any unclosed CloseComChannel
is implicitly closed in the following cases:
DiagManager
Important: A call of CloseComChannel closes the assigned
LogicalLink
, independent if multiple clients use the sameLogicalLink!
If an other client tries to use the already closedLogicalLink
, an UnknownTargetException will thrown.
Important: Closing a ComChannel releases all still open DiagServices associated with that
ComChannel
.
Note (For experts only): If the OTX-Runtime API is used an explicit or implicit created DiagService will be released automatically if the scope of the
DiagService
inside OTX was lost. If the OTX-DiagManager API is used outside the OTX-Runtime API a DiagService can be released by a call of ReleaseDiagService (C++ only).
Creating communication channels (ComChannel) takes time. Especially when a variant detection is to be carried out. Also, the author of an OTX sequence wants to use only one communication channel and not care about the lifetime of the communication channels. Therefore, open communication channels are cached.
Important: It is recommended to create each
ComChannel
with PVS (Perform-Variant-Selection).
Note: If PVS is used,
EcuVariantName
makes no sense. This is checked using the checker rule DiagCom_Chk201 "GetComChannel EcuVariantName must be omitted in PVS".
The table below shows the behavior of GetComChannel when GetComChannel is called for the first time. Identifier1
corresponds to the SHORT-NAME
of the relevant MCDLogicalLink
, for example "LL_Gateway"
. EcuVariantName1
and EcuVariantName2
are the SHORT-NAME
of the MCDDbEcuVariant
of the relevant MCDLogicalLink
, for example "EV_GatewaySupplier1_001"
. PVS means PerformVariantSelection
and is a parameter of GetComChannel.
Note:
EcuVariantName2
is the actual ECU variant.
Note: An error in variant identification always throws a LossOfComException.
Note: Row 8 is the default case in the OTX Development Environment.
No | Identifier | EcuVariantName | PVS | Result |
---|---|---|---|---|
1 | not exists | - | - | UnknownTargetException |
2 | Identifier1 | not exists | - | UnknownTargetException |
3 | Identifier1 | Empty String | false | BaseVariant |
4 | Identifier1 | NULL | false | BaseVariant |
5 | Identifier1 | EcuVariantName2 | false | EcuVariantName2 |
6 | Identifier1 | EcuVariantName1 | false | EcuVariantName1 |
7 | Identifier1 | Empty String | true | EcuVariantName2 |
8 | Identifier1 | NULL | true | EcuVariantName2 |
9 | Identifier1 | EcuVariantName2 | true | EcuVariantName2 |
10 | Identifier1 | EcuVariantName1 | true | EcuVariantName2 |
The behavior for each further creation of the same GetComChannel depends on the ComChannel
created first and is described in the following table.
Note: Many combinations make no technical sense and throw a DiagComException.
Note: If an exception occurs with GetComChannel, this has no effect on a previously created
ComChannel
.
Note: Row 46 is the default case in the OTX Development Environment.
No. | Identifier | 1. EcuVariantName | 1. PVS | 1. Result | 2. EcuVariantName | 2. PVS | 2. Result |
---|---|---|---|---|---|---|---|
01 | Identifier1 | Empty String | false | BaseVariant | Empty String | false | BaseVariant |
02 | NULL | BaseVariant | BaseVariant | ||||
03 | EcuVariantName2 | EcuVariantName2 | DiagComException | ||||
04 | EcuVariantName1 | EcuVariantName1 | DiagComException | ||||
05 | Empty String | true | EcuVariantName2 | DiagComException | |||
06 | NULL | EcuVariantName2 | DiagComException | ||||
07 | EcuVariantName2 | EcuVariantName2 | DiagComException | ||||
08 | EcuVariantName1 | EcuVariantName2 | DiagComException | ||||
09 | Empty String | false | BaseVariant | NULL | BaseVariant | ||
10 | NULL | BaseVariant | BaseVariant | ||||
11 | EcuVariantName2 | EcuVariantName2 | EcuVariantName2 | ||||
12 | EcuVariantName1 | EcuVariantName1 | EcuVariantName1 | ||||
13 | Empty String | true | EcuVariantName2 | EcuVariantName2 | |||
14 | NULL | EcuVariantName2 | EcuVariantName2 | ||||
15 | EcuVariantName2 | EcuVariantName2 | EcuVariantName2 | ||||
16 | EcuVariantName1 | EcuVariantName2 | EcuVariantName2 | ||||
17 | Empty String | false | BaseVariant | EcuVariantName2 | DiagComException | ||
18 | NULL | BaseVariant | DiagComException | ||||
19 | EcuVariantName2 | EcuVariantName2 | EcuVariantName2 | ||||
20 | EcuVariantName1 | EcuVariantName1 | DiagComException | ||||
21 | Empty String | true | EcuVariantName2 | DiagComException | |||
22 | NULL | EcuVariantName2 | DiagComException | ||||
23 | EcuVariantName2 | EcuVariantName2 | DiagComException | ||||
24 | EcuVariantName1 | EcuVariantName2 | DiagComException | ||||
25 | Empty String | false | BaseVariant | EcuVariantName1 | DiagComException | ||
26 | NULL | BaseVariant | DiagComException | ||||
27 | EcuVariantName2 | EcuVariantName2 | DiagComException | ||||
28 | EcuVariantName1 | EcuVariantName1 | EcuVariantName1 | ||||
29 | Empty String | true | EcuVariantName2 | DiagComException | |||
30 | NULL | EcuVariantName2 | DiagComException | ||||
31 | EcuVariantName2 | EcuVariantName2 | DiagComException | ||||
32 | EcuVariantName1 | EcuVariantName2 | DiagComException | ||||
33 | Empty String | false | BaseVariant | Empty String | true | DiagComException | |
34 | NULL | BaseVariant | DiagComException | ||||
35 | EcuVariantName2 | EcuVariantName2 | DiagComException | ||||
36 | EcuVariantName1 | EcuVariantName1 | DiagComException | ||||
37 | Empty String | true | EcuVariantName2 | DiagComException | |||
38 | NULL | EcuVariantName2 | DiagComException | ||||
39 | EcuVariantName2 | EcuVariantName2 | DiagComException | ||||
40 | EcuVariantName1 | EcuVariantName2 | DiagComException | ||||
41 | Empty String | false | BaseVariant | NULL | EcuVariantName2 | ||
42 | NULL | BaseVariant | EcuVariantName2 | ||||
43 | EcuVariantName2 | EcuVariantName2 | EcuVariantName2 | ||||
44 | EcuVariantName1 | EcuVariantName1 | EcuVariantName2 | ||||
45 | Empty String | true | EcuVariantName2 | EcuVariantName2 | |||
46 | NULL | EcuVariantName2 | EcuVariantName2 | ||||
47 | EcuVariantName2 | EcuVariantName2 | EcuVariantName2 | ||||
48 | EcuVariantName1 | EcuVariantName2 | EcuVariantName2 | ||||
49 | Empty String | false | BaseVariant | EcuVariantName2 | DiagComException | ||
50 | NULL | BaseVariant | DiagComException | ||||
51 | EcuVariantName2 | EcuVariantName2 | DiagComException | ||||
52 | EcuVariantName1 | EcuVariantName1 | DiagComException | ||||
53 | Empty String | true | EcuVariantName2 | DiagComException | |||
54 | NULL | EcuVariantName2 | DiagComException | ||||
55 | EcuVariantName2 | EcuVariantName2 | DiagComException | ||||
56 | EcuVariantName1 | EcuVariantName2 | DiagComException | ||||
57 | Empty String | false | BaseVariant | EcuVariantName1 | DiagComException | ||
58 | NULL | BaseVariant | DiagComException | ||||
59 | EcuVariantName2 | EcuVariantName2 | DiagComException | ||||
60 | EcuVariantName1 | EcuVariantName1 | DiagComException | ||||
51 | Empty String | true | EcuVariantName2 | DiagComException | |||
62 | NULL | EcuVariantName2 | DiagComException | ||||
63 | EcuVariantName2 | EcuVariantName2 | DiagComException | ||||
64 | EcuVariantName1 | EcuVariantName2 | DiagComException |
A DiagService represents a MCDDiagComPrimitive
(MCDDiagComPrimitive
in case of a MVCI-Server) of an MCDLogicalLink
. It contains request and response parameters and can be executed synchronously or asynchronously to the ECU.
A DiagService
can be explicit created using the following methods. Each call creates a new DiagService
object.
Note: A
DiagService
can be also implicit created, e.g. by calling the method GetComChannel withperformVariantSelection
istrue
.
Depending on its content, each DiagService
object occupies a considerable amount of memory. The used memory should be released as follows:
Implicit:
The DiagService
object is removed implicitly when the last remaining shared pointer owning the DiagService
object is removed.
Explicit:
The DiagService
object is removed explicitly by calling one of the following methods:
Method | Which DiagService will be released? |
---|---|
ReleaseDiagService (C++ only) | The given DiagService |
CloseComChannel | All DiagServices related to the given ComChannel |
DeselectProject | All DiagServices |
UnprepareInterface | All DiagServices |
UnprepareVciAccessLayer | All DiagServices |
CloseVciConnection | All DiagServices |
ResetDiagRuntimeSystem | All DiagServices |
CloseAllComChannels (C++ only) | All DiagServices |
Note: The OTX runtime manages the generated DiagService objects automatically. After executing a procedure, all DiagService objects generated by this procedure that have not already been cleaned up by CloseComChannel are removed.
A diagnostic runtime system according to ISO 22900 (MVCI) supports two communication modes:
MCDSystem::prepareInterface
) andMCDSystem::prepareVciAccessLayer
).In simple mode there is only one general VCI available. In extended mode there can be multiple VCIs. Both communication modes are mutually exclusive. So it can only be communicated in one. In order to communicate in another, the existing mode must be terminated beforehand.
Important: The DiagManager always starts with the simple communication mode.
Note: The simple mode is significantly faster when establishing and terminating a connection than the extended mode.
All actions and terms of the OTX extensions supported in DiagManager can be executed in the extended communication mode. Some actions and terms of the ComInterface extension can only be executed in the extended communication mode. They therefore require a change to the extended mode.
If the DiagManager is in the normal communication mode, the following terms of the ComInterface extension switch to the extended communication mode:
Note: Simple mode is sufficient for normal diagnostic communication. As soon as you want to communicate via the ComInterface extension or via DoIP, the extended mode is required.
Important: When changing to another communication mode, all open ComChannel must be closed, see ComChannel Lifetime - Closing. If necessary, previously opened
ComChannel
and DiagService are automatically reopened or created so that the application does not notice anything. The only exception are dynamically set request parameters of aDiagService
. These are currently not restored when switching from simple to extended mode.
With physical addressing, exactly one ECU responds to a request, see ExecuteDiagService. With functional addressing, more than one ECU can respond. The result of ExecuteDiagService can then contain more than one response.
Note: From the point of view of OTX, apart from the number of responses, there is no difference between physical and functional addressing in the runtime behavior described here.
Note: With inline mapping of ExecuteDiagService, in case of functional addressing only the first response is mapped. All other responses must be evaluated via "dynamic response", see ExecuteDiagService.
Note: The term GetComChannelIdentifierFromResponse can be used to retrieve information about various responding ECUs.
The DiagManager is designed to support the execution of several OTX processes at the same time. Even if each individual process would work without problems on its own, parallel execution can lead to a system overload because too many ComChannels are open at the same time. It does not matter which component of the system causes the overload. Possible components include the VCI or the control units in the vehicle. Gateway control units in particular are possible causes here.
In order to prevent a system overload, it is possible to specify a maximum number of ComChannels that can be opened simultaneously for the CommandProcessor. If this limit is exceeded, the CommandProcessor automatically begins to close open ComChannels
if they are not currently being used. If an implicitly closed ComChannel
is later accessed again by the diagnostic application, the ComChannel
is automatically reopened and, if necessary, another ComChannel
is closed for it.
Closing a ComChannel
also invalidates all DiagService handles that were previously created for it. If the diagnostic application accesses the handle again later, the DiagService must also be recreated. It receives a new handle. In order for the diagnostic application to continue working with the originally assigned handle, the DiagService handles must be translated.
Important: The ComChannel limitation can significantly reduce performance and should only switched ON if it is really necessary! Per default the
ComChannel
limitation is switched OFF.
By default, there is no limit to the number of ComChannels that can be opened simultaneously. This means that as many ComChannels
as the diagnostic application requests are opened. The diagnostic application itself is responsible for knowing and taking into account any restrictions that may exist.
Because in this case ComChannels
are not closed automatically, DiagServiceHandleMapping
is also not required, because the handles of the DiagServices
do not become invalid as long as the diagnostic application does not close them.
However, if a maximum number of simultaneously opened ComChannels
is specified, then the DiagServiceHandleMapping
is usually also required.
Within the CommandProcessor, the ComChannelManager component is responsible for managing the ComChannels
. Relevant methods:
The ComChannelManager is part of the CommandDispatcher, and the @ç CommandDispatcher is in turn part of the CommandProcessor. The procedure for creating the @ç CommandProcessor to set an upper limit of 8 channels could therefore look like this:
Note: Currently, it is not possible to query the CommandDispatcher used from the outside at the CommandProcessor. Therefore, to access the ComChannelManager, a new CommandDispatcher must be created and set using the @ç SetCommandDispatcher method. The
SetComamndDispatcher
method is therefore mandatory for this feature.