(C) 2022, 2023 - MBition GmbH
(C) 2022 - COVESA
(C) 2021 - Magnus Feuer
This document contains an introduction to the Interface Exchange (IFEX) framework and specification of the core Interface Description Language/Model (also known as ifex-idl and ifex-core). IFEX is the name for the technology (language, tools, etc.) behind the Vehicle Service Catalog (VSC) project.
License: Creative Commons Attribution 4.0 International License (CC-BY-4.0), described here
Documentation generated from: 8b82cf9e114b9d5c94b4ea783da640b2c062039e
The format supports the following features
Namespaces
Logical grouping of methods, events, properties, and defined data types that can be nested.
Interfaces
Logical grouping of methods, events, properties, and defined data types that are intended to be exposed as a ‘public’ (externally usable) interface from a software component.
Methods
A function or remote-procedure-call, sent to and executed by a particular targeted component (server). Methods can have input and output parameters, as well as separate return-parameters, and errors.
Rich type system Named data types that can be enumerations, structs or typedefs, and collections (arrays) of types, and each of those types can be nested. Type aliases are supported, and constraints such as a limited value-range (work in progress).
Events
A fire-and-forget call/message, sent to or invoked on zero or more subscribing instances. The Event has no return a value and does not guarantee delivery (refer to target-dependent details).
Data Properties
An observable shared state object that can be read and set, and which is available to all* subscribing entities.
(*individual access control rules are of course possible to apply in the target environment) .
Layered architecture and Deployment files
IFEX Core IDL is designed to be a fundamental format for describing all sorts of software interfaces. Interface descriptions should be as generic as possible, meaning the same interface description can be reused in a completely different environment. The IFEX concept adds on a layered architecture that adds deployment-specific data to an interface definition so that it can avoid cluttering the core IDL. Other composable features are likely to be created using the generic layering concept. This separation of interface and deployment was pioneered by Franca IDL and IFEX continues and extends the principle.
This current version of the IFEX Core IDL has removed the “service:” keyword but the concept of a service should still be defined in terms of the interfaces the service provides. (See next chapter).
IFEX Core IDL does not include the name Signal but supports both Events and Properties that do cover two different interpretations of the word signal. See next chapter for a more detailed analysis.
For example:
Please note that in the text, “target-environment dependent”, may sometimes be shortened to simply target-dependent and similar simplifications may occur.
NOTE: Don’t mistake this for what most programming environments describe, which is to define a single enumeration, or structured/variant type, where each returned value may indicate a different “error”. What IFEX provides is the possibility of defining multiple different error returns, each with their own name and type (similar to multiple input or output-variables in a function). Through overlays, that enables efficiently separating business-logic errors (that are known when the interface is defined), from transport errors (that are only known later, when a particular target environment has been selected). The difference is subtle and of course the generated code might be required to combine the information into a single struct/variant/union type because of limitations, but the difference is that it can now be done at the deployment stage, and not at the interface definition stage.
Avoiding event confusion:
An IFEX Event is not a persistent data item, and thus has no built-in concepts of active-low/high, level or edge-trigger, rising/falling edge, etc. (other than what its name and documentation indicates). It is there to expressly indicate a particular thing “has happened”. It happened “at this point in time”, and is communicated as nearly as possible to the time of the happening.
An IFEX Event is a separate and expressly defined object in the interface description. It should be used for something central to the “business-logic” of the interface. It is not to be mixed up with lower level “happenings” in a system that do not need to be expressly defined. Events shall not be confused with messages that are automatically sent by some target environment directly, either that they are always done (hidden as part of that implementation) or as a result of the already encoded behavior of other objects already in the IDL.
Design tip: If there is a need to model On/Off events, to avoid duplicating each one into two different Events -> give the event a single name and transfer a boolean as argument: FooState(bool) where the true/false value indicates the on/off state. Another option might be to define an observable boolean data Property and use the target environment’s Pub/Sub capability to get updates on its state. (Depending on the details of the target environment, the latter might also give reliability guarantees that Events do not have).
Conceptually, an Event can be sent from client to server or from server to client. (*) TO CLARIFY: Shall the direction of an event be defined, and how?
If some events are to be transferred as a “broadcast” (from server to all clients) while other events would be addressed uniquely to particular client(s), then define this difference as extra information in a deployment model / target mapping. It is not specified in the IFEX core IDL interface description.
In computing systems there are two main paradigms regarding invocation of a procedure/function: Blocking/synchronous vs. Non-blocking/asynchronous.
In a blocking/synchronous environment, the client invokes an operation (“calls a function”) and will halt until the operation is completed (“the function returns”) and then continue its own execution flow. When completed, a return-value (result) may be communicated back to the client.
In an asynchronous setup, a client can trigger the start of an operation and then continue doing other work while the method executes in parallel. Programming languages and environments have different mechanisms for either notifying the client that the operation is finished, or for the client to ask if it is finished or, at some later point in time decide to go into a “blocking” mode and wait for the operation to finish. In any case, the executing server may will report back the result in some manner when the operation is finished, but it could also give continuous reports as to the progress of the function (“streaming updates”).
In the IFEX core IDL, methods can only be defined without defining their (synchronous/asynchronous) invocation strategy. It is more flexible to define this separately in a deployment-model/target-mapping because it leads to interface descriptions that can be reused in a wider set of circumstances. Perhaps it is true that some operations only are suited for one or the other, but many operations can in general be done in either a synchronous or asynchronous manner. The desire for sync vs. async might change in new circumstances, and the availability of sync/async might also be constrained by the target environment capability. To encourage the design of widely reusable and generic interfaces, the sync/async aspect is therefore defined separate from the main IDL.
In all cases, an IFEX Method may define a Return Value type. The return value can be defined for the interface description, without knowing the manner that the method will be invoked (e.g. the chosen communication protocol). IFEX-IDL-language has the unique feature of using the Return Value type to serve two different purposes in sync vs async situations:
** Design note: This is already in itself a very powerful mechanism and should suffice in a majority of cases, but if any additional status/streaming-data functionality is required, that may of course be done by defining a data Property in the interface, whose value is used to indicate the status of the system for the executing method. This would enable to listen (subscribe) to update to the Property, or fetch it on-demand, depending on what features the target mapping provides for Properties. Note that there is no formal way to describe the relationship between Property and Method in this design approach - it would rely on documenting the relationship in descriptions.
***Design note 2: While the interface can now be defined without deciding up front about synchronous/asynchronous operation, if an async operation may be expected it is still a good idea to design the return value with this in mind. It is likely to include something to indicate that processing is under way. For example the streaming returns during an operation might be: Started, Processing…, Processing…, Processing…, Done!”` (Note that this, like most details, can be extended by overlays.)
While a return value can also indicate that the operation did NOT complete successfully, the more capable Errors concept should not be overlooked.
It might be noticed that the IFEX core IDL does not seem to have an explicit type for “streaming data” type interfaces. However, when reading the previous chapter about asynchronous methods it should be clear that there is a natural way to do it:
Note here, that the explicit separation of Error s from return value, which is most other programming and IDL environments fail to do, enables modeling Error information that would be returned to the client when a problem occurs, and that is completely independent of the return type that describes what the streaming data looks like.
Here we have a situation where it is likely to be known at interface-definition time how the method is intended to be used. It is therefore recommended that the interface designer makes note of this in a comment, that the particular method indicates a streaming interface.
As described in the previous chapter, to make a method asynchronous will require a target-environment deployment layer that annotates the method to be “asynchronous”. If it is necessary, the design of that target mapping is of course free to use more explicit metadata to make it even clearer and since Layer Types are completely open for design, it could also add more information such as the data rate and exact method of streaming, and so on.
Example (not normative):
methods:
- name: mymethod
asynchronous: true
streaming: true # example, the layer design (i.e. not part of this IDL core specification) decides what makes sense
The current version of the IFEX Core IDL removed the “service:” keyword that was in the earliest specification. In the future a new concept may be appropriate to add but at the moment it is expected that any definition of “service” will be defined externally from the core IDL, and make reference to IFEX Core IDL file(s) that describe Interfaces.
It is still worthwhile to prepare our understanding of what a service is:
The word Signal is interpreted by some as the transfer of a value associated with a name/id for what that value represents. This suggests that a signal is something happening at a point in time. Such value transfer ought to be semantically equivalent to single-argument Event, and is therefore supported using Event in IFEX. Another interpretation is that the word Signal rather represents the underlying data item itself, independent of what time update-events are sent. In this second case, value-transfers are defined more as a consequence of the data changing, or a predefined frequency of update - for example “subscribing to changes of a Signal”. In this second interpretation the Signal is represented by a Property in IFEX. The Vehicle Signal Specification (VSS) defines “signals” that have a name, a datatype, a unit and meaning but the transfer of data is defined by separate protocols built on top of VSS. In other words, VSS typically uses the the second interpretation, and VSS Signals can then be represented by Properties in IFEX. (Refer to the separate analysis of the IFEX/VSS relationship).
IFEX namespaces can have a major and minor version, specified by
major_version
and minor_version
keys, complemented by an additional
free format string named version_label
. These are defined as optional
in the core IDL, but most development processes ought to treat them as mandatory
at some point in the working process, to support management of API
compatibility between components.
There is also an optional patch_version
number, to simplify compatibility
with other interface descriptions that use the semantic versioning principle.
(Please see the recommendation against using patch_version
in new
designs, described in the Interface Versioning chapter).
Namespace version management can be used to understand the impact of changes on various namespace levels and how this may affect compatibility. For general API-compatibility evaluation, the version on the Interface node might be used more often, however.
Namespace versioning shall follow the Semantic Versioning principle. Follow the more detailed description under Interface Versioning.
Namespace versioning can be used build-time to ensure that the correct version of all needed namespace implementations are deployed.
An Interface is essentially a specialization of the Namespace concept. Interfaces shall be versioned in the same manner, and are even more important since they are the likely place to determine if components will communicate correctly (i.e. use the compatible versions of Interface description).
There could be rules implemented in validation tools that ensure interface versions match the versioning of namespaces. (E.g. Don’t claim an interface is compatible if its parent namespace has changed in an incompatible way).
Versioning shall follow the Semantic Versioning principle:
Bumped minor numbers identifies backward-compatible additions to the previous version. This means that if a client requires version 1.3 of a server namespace and its methods, it knows that it can safely interface a server implementation of version 1.4 of that same namespace.
Bumped major versions identifies non-compatible changes to the previous version, such as a changed method signature. This means that a client requiring version 1.3 of a server knows that it cannot invoke a version 2.0 server implementation of that interface since that implementation is not backward compatible.
For details that are not mentioned here, refer to https://semver.org, but if there is a contradiction, this specification shall take precedence.
An optional field for patch version exists but it is recommended to avoid it in most development processes since minor (or major) version should be used indicate an actual change to the interface. Unlike code, in this context we are mostly interested in if there is a change in the interface and if it is backwards compatible.
If patch_version
is used anyway, it ought to be for documentation related
changes but small changes such as formatting or fixing a spelling mistake in
comments might also be recognized by using the git commit hash, which is a
guaranteed unique identifier of the IDL file contents. A processes that uses
that commit hash won’t rely on a human remembering to update it, and could be
an efficient replacement compared to constantly having to update the
patch-level version number. In the end, it is however up to each adopter to
decide on which process they want to use.
Note also the additional field version_label
that is a free-form field in
which implementations can place their own type of identifying information.
Companies might have their own compatibility information, their own way
of describing interface versions, or other information that goes into this
free-form text. Some kind of unique hash of the interface content could be useful,
but it then requires hashing the content without the version_label line itself of course.
If the file is going to be transferred from one git to another system, the process might fill in the version_label using the git commit hash after the file is taken out of git and transferred to that other system. But it is of course not possible write the commit hash into the file beforehand and commit that content into git (because the actual commit hash is not decided until the file is committed - and it would effectively depend on itself). In these cases, perhaps the development process may choose to perform another hash calculation (SHA/MD5) of the interface content (again leaving out of course the version_label lines themselves since there would otherwise be a circular dependency again).
Ultimately, versioning can be used build-time to ensure that the correct version of all needed interface/namespace implementations are deployed, while also detecting if multiple, non-compatible versions of an interface are required to be supported at the same time.
These are the supported fundamental (primitive) types, as generated from the source code model. These primitive types are identical to the types used in the VSS (Vehicle Signal Specification) model, and of course they should easily match typical datatypes in other interface description systems.
Name | Description | Min value | Max value |
---|---|---|---|
uint8 | unsigned 8-bit integer | 0 | 255 |
int8 | signed 8-bit integer | -128 | 127 |
uint16 | unsigned 16-bit integer | 0 | 65535 |
int16 | signed 16-bit integer | -32768 | 32767 |
uint32 | unsigned 32-bit integer | 0 | 4294967295 |
int32 | signed 32-bit integer | -2147483648 | 2147483647 |
uint64 | unsigned 64-bit integer | 0 | 2^64 - 1 |
int64 | signed 64-bit integer | -2^63 | 2^63 - 1 |
boolean | boolean value | False | True |
float | floating point number | -3.4e -38 | 3.4e 38 |
double | double precision floating point number | -1.7e -300 | 1.7e 300 |
string | character string | N/A | N/A |
The IFEX approach implements a layered approach to the definition of interfaces, and potentially other aspects of a system. The core interface file (Interface Description Language, or Interface Description Model) shall contain only a generic interface description that can be as widely applicable as possible.
As such, it avoids including specific information that only applies in certain interface contexts, such as anything specific to the chosen transport protocol, the programming language, and so on.
Each new Layer Type defines what new metadata it provides to the overall model. A Layer Type Specification may be written as a human-readable document, but is often provided as a “YAML schema” type of file, that can be used to programatically validate layer input against formal rules.
Layers do not always need to add new types of information. It is possible to ‘overlay’ files that use the same schema as an original file (such as the ifex-idl), for the purpose of adding some details that were not yet defined, removing nodes, or even redefining/changing the definition of some things defined in the original file.
In other words, tools are expected to be able to process the layer types that are relevant for the task at hand, but furthermore, some tools are expected to process multiple files of the same type and to merge their contents according to predefined rules. Conflicting information could for example be handled by writing a warning, or the tool may stipulate that the last provided layer file to takes precedence over previous definitions. (Refer to detailed documentation for each tool).
An example of this:
File: comfort-service.yml
name: comfort
typedefs:
- name: movement_t
datatype: int16
min: -1000
max: 1000
description: The movement of a seat component
File: redefine-movement-type.yml
name: comfort
typedefs:
- name: movement_t
datatype: int8 # Replaces int16 of the original type
Tools that combine this information will end up processing a combined YAML structure that looks like this, in this case following the principle that the last-definition takes precedence.
name: comfort
typedefs:
- name: movement_t
datatype: int8 # (Replaced datatype)
min: -1000
max: 1000
description: The movement of a seat component
Most layers*** will follow the same hierarchical structure as the original
interface definiton written in the IFEX Core IDL. If a layer object list
element (e.g. events
) is also defined in the IFEX file, the IFEX’s list will
traversed recursively and extended by the deployment file’s corresponding list.
** For more information on layer types and different strategies, refer to the developers manual.
In this example, an overlay is used to add a new parameter to an existing interface. This is a bit of a peculiar case, but some development strategies may use this to more clearly local modifications on top of a standard interface description - such as an industry standard API. Separating it into an overlay makes it more explicit, but this should be understood as an example rather than a design guideline.
File: comfort-service.yml
name: comfort
events:
- name: seat_moving
description: The event of a seat starting or stopping movement
in:
- name: status
datatype: uint8
- name: row
datatype: uint8
File: add_seat_moving_in_parameter.yml
name: comfort
events:
- name: seat_moving:
in:
- name: extended_status_text
datatype: string
The combined structure to be processed will look like the following: (We show it here using YAML syntax, but this combined representation might only exist only inside the tool memory, after reading more than one input file.)
name: comfort
events:
- name: seat_moving
description: The event of a seat starting or stopping movement
in:
- name: status
datatype: uint8
- name: row
datatype: uint8
- name: extended_status_text
datatype: string
Note: There is not a fixed list of layer types – while some might be agreed upon in a community and documented within the IFEX project, the capability is also there to allow extensions that have not yet been envisioned. Some aspects of API and system design might be unique to one company’s way of working, and therefore defined and used only there.
Deployment layer, a.k.a. Deployment Model files, is a specialization of the general layers concept. This terminology is used to indicate a type of layer that in adds additional metadata that is directly related to the interface described in the IDL. It is information needed to process, or interpret, IFEX interface files in a particular target environment.
An example of deployment file data is a D-Bus interface specification to be used for a namespace, or a SOME/IP method ID to be used for a method call.
By separating the extension data into their own deployment files the core IFEX specification can be kept independent of deployment details such as network protocols and topology.
An example of a IFEX file sample and a deployment file extension to that sample is given below:
File: comfort-service.yml
name: comfort
namespaces:
- name: seats
description: Seat interface and datatypes.
structs: ...
methods: ...
...
File: comfort-dbus-deployment.yml
name: comfort
namespaces:
- name: seats
dbus_interface: com.genivi.cabin.seat.v1
The combined YAML structure to be processed will look like this:
name: comfort
namespaces:
- name: seats
description: Seat interface and datatypes.
dbus_interface: com.genivi.cabin.seat.v1
structs: ...
methods: ...
The semantic difference between a regular IFEX file included by an
includes
list object and a deployment file is that the deployment
file can follow a different specification/schema and add keys that
are not allowed in the plain IDL layer. In the example above, the
dbus_interface
key-value pair can only be added in a deployment file since
dbus_interface
is not a part of the regular IFEX IDL file syntax.
For more information about Layer Types and Layer design, refer to the corresponding chapter in the developers-manual.md
A Vehicle Service Catalog is stored in one or more YAML files. The
root of each YAML file is assumed to be a namespace
object and needs
to contain at least a name
key, and, optionally, a description
. In
addition to this other namespaces, includes
, datatypes
, methods
,
events
, and properties
can be specified.
A complete IFEX file example is given below:
NOTE: This example might be outdated
---
name: comfort
major_version: 2
minor_version: 1
description: A collection of interfaces pertaining to cabin comfort.
# Include generic error enumeration to reside directly
# under comfort namespace
includes:
- file: vsc-error.yml
description: Include standard VSC error codes used by this namespace
namespaces:
- name: seats
description: Seat interface and datatypes.
typedefs:
- name: movement_t
datatype: uint16
structs:
- name: position_t
description: The position of the entire seat
members:
- name: base
datatype: movement_t
description: The position of the base 0 front, 1000 back
- name: recline
datatype: movement_t
description: The position of the backrest 0 upright, 1000 flat
enumerations:
- name: seat_component_t
datatype: uint8
options:
- name: base
value: 0
- name: recline
value: 1
methods:
- name: move
description: Set the desired seat position
in:
- name: seat
description: The desired seat position
datatype: movement.seat_t
events:
- name: seat_moving
description: The event of a seat beginning movement
in:
- name: status
description: The movement status, moving (1), not moving (0)
datatype: uint8
properties:
- name: seat_moving
description: Specifies if a seat is moving or not
type: sensor
datatype: uint8
The following chapters specifies all YAML objects and their keys
supported by IFEX. The “Lark grammar” specification refers to the Lark
grammar that can be found here.
The terminals used in the grammar (LETTER
, DIGIT
, etc) are
imported from
common.lark
The chapters that follow this one specify the node types for the core interface language/model. They are generated from a “source of truth” which is the actual python source code of ifex_ast.py
. This means that while the examples are free-text and may need manual updating, the list of fields and optionality should always match the behavior of the tool(s). => Always trust the tables over the examples, and report any discrepancies.
Dataclass used to represent IFEX Namespace.
A namespace is a logical grouping of other objects, allowing for separation of datatypes, methods, events, and properties into their own spaces that do not interfere with identically named objects in other namespaces. Namespaces can be nested inside other namespaces to an arbitrary depth, building up a scalable namespace tree. Namespaces can be reused either locally in a single file via YAML anchors, or across YAML files using the includes object. The root of a YAML file is assumed to be a namespaces object, and can contain the keys listed below.
A namespace example is given below.
namespaces:
- name: seats
major_version: 1
minor_version: 3
description: Seat interface and datatypes.
Field Name | Contents |
---|---|
name | A single str |
Field Name | Contents |
---|---|
description | A single str |
major_version | A single int |
minor_version | A single int |
version_label | A single str |
events | A list of Events |
methods | A list of Methods |
typedefs | A list of Typedefs |
includes | A list of Includes |
structs | A list of Structs |
enumerations | A list of Enumerations |
properties | A list of Propertys |
namespaces | A list of Namespaces |
interface | A single Interface |
Dataclass used to represent IFEX Event.
Each events list object specifies a fire-and-forget call, executed by zero or more subscribing instances, that does not return a value. Execution is best effort to UDP level with server failures not being reported.
A events sample list object is given below:
events:
- name: seat_moving
description: Signal that the seat has started or stopped moving
in:
- name: status
description: The movement status, moving (1), not moving (0)
datatype: boolean
- name: row
description: The row of the seat
datatype: uint8
Field Name | Contents |
---|---|
name | A single str |
Field Name | Contents |
---|---|
description | A single str |
input | A list of Arguments |
Dataclass used to represent IFEX method Argument.
methods:
- name: current_position
input:
- name: row
description: The desired seat to row query
datatype: uint8
range: $ < 10 and $ > 2
Field Name | Contents |
---|---|
name | A single str |
datatype | A single str |
Field Name | Contents |
---|---|
description | A single str |
arraysize | A single int |
range | A single str |
Dataclass used to represent IFEX Event.
Each methods list object specifies a method call, executed by a single server instance, that optionally returns a value. Execution is guaranteed to TCP level with server failure being reported.
A methods sample list object is given below:
methods:
- name: current_position
description: Get the current position of a seat
input:
- name: row
description: The desired seat to row query
datatype: uint8
range: $ < 10 and $ > 2
- name: index
description: The desired seat index to query
datatype: uint8
range: $ in_interval(1,4)
output:
- name: seat
description: The state of the requested seat
datatype: seat_t
errors:
- datatype: .stdvsc.error_t
range: $ in_set("ok", "in_progress", "permission_denied")
Field Name | Contents |
---|---|
name | A single str |
Field Name | Contents |
---|---|
description | A single str |
errors | A list of Errors |
input | A list of Arguments |
output | A list of Arguments |
returns | A list of Arguments |
Dataclass used to represent a IFEX method error.
The optional error element defines an error value to return. Note that the concept allows for multiple Errors. This is easy to misunderstand: It is not only multiple different error values as you are used to from most programming environments. Multiple value choices can be handled by a single Enumeration error type. The concept also allows multiple independent return parameters, each having their own data type (and name).
The purpose of this is to be able to separate different error categories and to define them independently using layers. For example, a method is likely to have a collection of business-logic errors defined in its interface description and represented by one enum type. At a later time transport-protocol specific errors can be added when the interface is deployed over a certain protocol, and that error parameter has a different name and a different type (enumeration or otherwise).
Error elements are returned in addition to any out elements specified for the method call.
Please see the methods sample code above for an example of how error parameter lists are used If no error element is specified, no specific error code is returned. Results may still be returned as an out parameter`
methods:
- name: current_position
description: Get the current position of a seat
errors:
- name: "progress"
datatype: .stdvsc.error_t
range: $ in_set("ok", "in_progress", "permission_denied")
- <possibly additional error definition>
Field Name | Contents |
---|---|
datatype | A single str |
Field Name | Contents |
---|---|
name | A single str |
description | A single str |
arraysize | A single int |
range | A single str |
Dataclass used to represent IFEX Typedef.
A Typedef is an alias to an existing fundamental type or defined type, including structs, enumerators, etc. It can also be used to name and define a variant type. The new data type name can be used in the definition of other datatypes, method- and event-parameters, and properties.
A typedefs list object example is given below:
typedefs:
- name: movement_t
datatype: int16
min: -1000
max: 1000
description: The movement of a seat component
Variant types
The fields datatype
and datatypes
are mutually exclusive - only one of them may have a value. The field datatypes
is used to specify multiple types associated with this type name. Doing this makes it a variant
type. It is also possible to define a variant type using the variant<a,b,c>
-style syntax in any location requiring a datatype, but the ability to specify it as a list can be more useful if the number of types is large. Handling this as a list can also allow Layers to extend a variant type more conveniently.
typedefs:
- name: StringOrStruct
datatypes:
- string
- MyStruct
- OtherStruct
description: The Thing, represented in one of 3 ways.
NOTE! The fields datatype
and datatypes
are defined as optional in the language model, but one of them must be defined.
Field Name | Contents |
---|---|
name | A single str |
Field Name | Contents |
---|---|
datatype | A single str |
datatypes | A list of strs |
description | A single str |
arraysize | A single int |
min | A single int |
max | A single int |
Dataclass used to represent IFEX Include.
Each includes list object specifies a IFEX YAML file to be included into the namespace hosting the includes list. The included file’s structs, typedefs, enumerators, methods, events, and properties lists will be appended to the corresponding lists in the hosting namespace.
A includes sample list object is given below:
namespaces:
- name: top_level_namespace
includes
- file: vsc-error.yml;
description: Global error used by methods in this file
Field Name | Contents |
---|---|
file | A single str |
Field Name | Contents |
---|---|
description | A single str |
Dataclass used to represent IFEX Struct.
Each structs list object specifies an aggregated data type. The new data type can be used by other datatypes, method & event parameters, and properties.
A structs list object example is shown below:
structs:
- name: position_t
description: The complete position of a seat
members:
- name: base
datatype: movement_t
description: The position of the base 0 front, 1000 back
- name: recline
datatype: movement_t
description: The position of the backrest 0 upright, 1000 flat
Field Name | Contents |
---|---|
name | A single str |
Field Name | Contents |
---|---|
description | A single str |
members | A list of Members |
Dataclass used to represent IFEX Struct Member.
Each members list object defines an additional member of the struct. Each member can be of a fundamental or defined/complex datatype.
Please see the struct sample code above for an example of how members list objects are used.
structs:
- name: position_t
description: The complete position of a seat
members:
- name: base
datatype: movement_t
description: The position of the base 0 front, 1000 back
Field Name | Contents |
---|---|
name | A single str |
datatype | A single str |
Field Name | Contents |
---|---|
description | A single str |
arraysize | A single int |
Dataclass used to represent IFEX Enumeration.
Each enumerations list object specifies an enumerated list (enum) of options, where each option can have its own integer value. The new data type defined by the enum can be used by other datatypes, method & event parameters, and properties.
A enumerations example list object is given below:
enumerations:
- name: seat_component_t
datatype: uint8
options:
- name: base
value: 0
- name: cushion
value: 1
Field Name | Contents |
---|---|
name | A single str |
datatype | A single str |
options | A list of Options |
Field Name | Contents |
---|---|
description | A single str |
Dataclass used to represent IFEX Enumeration Option.
Each options list object adds an option to the enumerator.
Please see the enumerations sample code above for an example of how options list objects are used.
options:
- name: base
value: 0
description: description of the option value
Field Name | Contents |
---|---|
name | A single str |
value | A single Any |
Field Name | Contents |
---|---|
description | A single str |
Dataclass used to represent IFEX Property.
Each properties list object specifies a shared state object that can be read and set, and which is available to all subscribing entities. A properties sample list object is given below, together with a struct definition:
properties:
- name: dome_light_status
description: The dome light status
datatype: dome_light_status_t
Field Name | Contents |
---|---|
name | A single str |
datatype | A single str |
Field Name | Contents |
---|---|
description | A single str |
arraysize | A single int |
Dataclass used to represent IFEX Interface
An Interface is a container of other items in a similar way as a Namespace, but it does not introduce a new namespace level. Its purpose is to explicitly define what shall be considered part of the exposed as a “public API” in the output.
Note that as with all IFEX concepts, the way it is translated into target code could be slightly varying, and controlled by the target mapping and deployment information, but all mappings shall strive to stay close to the IFEX expected behavior. Thus, the Interface section would omit for example internal helper-methods and type definitions that are only used internally, while those definitions might still need to be in the parent Namespace for the code generation to work.
An Interface can contain all the same child node types as Namespace can, except for additional (nested) Interfaces. As mentioned, it does NOT introduce an additional namespace level regarding the visibility/reacahbility of the items. Its contents is not hidden from other Namespace or Interface definitions within the same Namespace. To put it another way, from visibility/reachability point of view all the content inside an interface container is part of the “parent” Namespace that the Interface object is placed in. Of course, if additional nested namespaces are placed below the Interface node, those Namespaces introduce new namespace levels, as usual.
Only one Interface can be defined per Namespace, and it cannot include other Interfaces
An Interface example is given below.
namespaces:
- name: seats
major_version: 1
minor_version: 3
description: Seat interface and datatypes.
interface:
typedefs:
- ...
methods:
- ...
properties:
- ...
Field Name | Contents |
---|---|
name | A single str |
Field Name | Contents |
---|---|
description | A single str |
major_version | A single int |
minor_version | A single int |
version_label | A single str |
events | A list of Events |
methods | A list of Methods |
typedefs | A list of Typedefs |
includes | A list of Includes |
structs | A list of Structs |
enumerations | A list of Enumerations |
properties | A list of Propertys |
namespaces | A list of Namespaces |