This exporter generates a valid GraphQL schema out of the VSS specification. The schema is constructed according to the GraphQL Schema Language.
VSS resembles a hierarchical tree, where a concept of interest is a node in it.
The actual data point appears always as a leaf
in the tree (i.e., one of type attribute
, sensor
, or actuator
).
The context for those leaf
nodes is implicitly captured by grouping them under particular branch
nodes.
For example, in the following diagram, the window position results in the name Vehicle.Cabin.Door.Row1.DriverSide.Window.Position
. Here, Row1.DriverSide
refers to a particular instance of the concept Door
.
graph TD
Vehicle --> Cabin
Vehicle --> OtherBranch
Cabin --> Door
Door --> Row1
Row1 --> DriverSide
DriverSide --> Window
Door --> OtherInstance
Window --> Position
Window --> OtherLeaf
OtherBranch --> SomeLeaf
classDef white fill:#FFFFFF,stroke:#000000,stroke-width:2px,color:#000000;
classDef gray fill:#F5F5F5,stroke:#666666,stroke-width:2px,color:#000000;
classDef blue fill:#DAE8FC,stroke:#6C8EBF,stroke-width:2px,color:#000000;
classDef green fill:#D5E8D4,stroke:#82B366,stroke-width:2px,color:#000000;
classDef orange fill:#FFE6CC,stroke:#D79B00,stroke-width:2px,color:#000000;
classDef yellow fill:#FFF2CC,stroke:#D6B656,stroke-width:2px,color:#000000;
classDef red fill:#F8CECC,stroke:#B85450,stroke-width:2px,color:#000000;
classDef purple fill:#E1D5E7,stroke:#9673A6,stroke-width:2px,color:#000000;
class Vehicle,Cabin,Door,Window,OtherBranch blue;
class Row1,DriverSide,OtherInstance yellow;
class Position,OtherLeaf,SomeLeaf red;
The following table shows the possible metadata for VSS elements:
VSS metadata item | Description | Mandatory? | In branch ? |
In leaf ? |
---|---|---|---|---|
fqn |
Fully qualified name of the element (aka., VSS Signal ) |
Yes | Yes | Yes |
type |
One of branch , attribute , sensor , or actuator |
Yes | Yes | Yes |
description |
Description of the element | Yes | Yes | Yes |
comment |
Additional comments about the element | No | Yes | Yes |
deprecation |
Deprecation status of the element | No | Yes | Yes |
instances |
Labels identifying multiple occurrences | No | Yes | No |
datatype |
Data type of the leaf element | Yes | No | Yes |
unit |
Unit of measurement for the leaf element | No | No | Yes |
min |
Minimum value for the leaf element | No | No | Yes |
max |
Maximum value for the leaf element | No | No | Yes |
allowed |
Allowed values for the leaf element | No | No | Yes |
default |
Default value for the leaf element | No | No | Yes |
fqn
- The
fqn
is used to construct the name of a GraphQLtype
.
- The
type: branch
- We distiguish a pure VSS
branch
from those that areinstances
. The aim is to focus the modeling process only on the abstract concepts that capture the intended meaning without repetition of entries. - Only if the
branch
is not an instance of another branch, aGraphQL type
whith name based on thefqn
is created.
- We distiguish a pure VSS
description
- A doc string above the GraphQL
type
definition.
- A doc string above the GraphQL
comment
- Included in the doc string with the prefix
@comment
.
- Included in the doc string with the prefix
deprecation
- Using the GraphQL
@deprecated
directive.
- Using the GraphQL
instances
- An
instance:
GraphQLfield
is created inside thetype
definition. This field points to a particularenum
. - A GraphQL
enum
named as<instantiatedBranchName>InstanceEnum
is created with the values specified in the vspec. - The parent node to which the instantiatable branch belongs will contain a field for that in the plural form. Also, the assotiated type for the value is created as an array to indicate the possibility of having multiple instances of such an element. For example, if the type
Cabin
is expected to have multiple doors, then a fielddoors: [Door]
will appear there.
- An
For example, considering the concepts Vehicle
, Cabin
, Door
, and Window
.
They are specified in vspec
as follows:
Vehicle:
description: High-level vehicle data.
type: branch
Vehicle.Cabin:
description: All in-cabin components, including doors.
type: branch
Vehicle.Cabin.Door:
type: branch
instances:
- Row[1,2]
- ["DriverSide","PassengerSide"]
description: All doors, including windows and switches.
Vehicle.Cabin.Door.Window:
type: branch
description: Door window status. Start position for Window is Closed.
If we directly expand the tree, it will result in unnecessary repetition of the specification for the instantiated branches.
graph TD
Vehicle --> Cabin
Cabin --> Door
Door --> Row1.DriverSide
Door --> Row2.DriverSide
Door --> Row1.PassengerSide
Door --> Row2.PassengerSide
Row1.PassengerSide --> Row1.PassengerSide.Window
Row2.PassengerSide --> Row2.PassengerSide.Window
Row1.DriverSide --> Row1.DriverSide.Window
Row2.DriverSide --> Row2.DriverSide.Window
classDef blue fill:#DAE8FC,stroke:#6C8EBF,stroke-width:2px,color:#000000;
classDef yellow fill:#FFF2CC,stroke:#D6B656,stroke-width:2px,color:#000000;
class Vehicle,Cabin,Door,Row1.PassengerSide.Window,Row2.PassengerSide.Window,Row1.DriverSide.Window,Row2.DriverSide.Window blue;
class Row1.PassengerSide,Row2.PassengerSide,Row1.DriverSide,Row2.DriverSide yellow;
Click here to expand an example YAML export
Vehicle:
description: High-level vehicle data.
type: branch
Vehicle.Cabin:
description: All in-cabin components, including doors.
type: branch
Vehicle.Cabin.Door:
description: All doors, including windows and switches.
type: branch
Vehicle.Cabin.Door.Row1:
description: All doors, including windows and switches.
type: branch
Vehicle.Cabin.Door.Row1.DriverSide:
description: All doors, including windows and switches.
type: branch
Vehicle.Cabin.Door.Row1.DriverSide.Window:
description: Door window status. Start position for Window is Closed.
type: branch
Vehicle.Cabin.Door.Row1:
description: All doors, including windows and switches.
type: branch
Vehicle.Cabin.Door.Row1.DriverSide:
description: All doors, including windows and switches.
type: branch
Vehicle.Cabin.Door.Row1.DriverSide.Window:
description: Door window status. Start position for Window is Closed.
type: branch
Vehicle.Cabin.Door.Row2:
description: All doors, including windows and switches.
type: branch
Vehicle.Cabin.Door.Row2.DriverSide:
description: All doors, including windows and switches.
type: branch
Vehicle.Cabin.Door.Row2.DriverSide.Window:
description: Door window status. Start position for Window is Closed.
type: branch
To convey the same information in a compact way, the GraphQL correspondance would be:
"""All in-cabin components, including doors."""
type Cabin {
doors: [Door]
}
"""All doors, including windows and switches."""
type Door {
instanceLabel: doorInstanceEnum
window: Window
}
"""Door window status. Start position for Window is Closed."""
type Window {
...
}
"""Set of possible values for the instance name of a Door."""
type doorInstanceEnum {
ROW1_DRIVERSIDE
ROW1_PASSENGERSIDE
ROW2_DRIVERSIDE
ROW2_PASSENGERSIDE
}
fqn
- The last part of the
fqn
(i.e., the node's name itself) becomes the name of a GraphQLfield
inside a particular GraphQLtype
.
- The last part of the
type
- Since GraphQL specifies a contract between the data producer and data consumer. The specified data can be made readable (via
Query
) and/or writtable (viaMutation
). - Optional: Regardless of the
VSS type
, every leaf can have a field in aQuery
to indicate that the value can be read. This is listed as optional because some concepts might not be desired to be queried atomically. - Optional: If
VSS type
isactuator
, aMutation
for that concept could be specified. This is listed as optional because some concepts might not be desired to be modifiable atomically.
- Since GraphQL specifies a contract between the data producer and data consumer. The specified data can be made readable (via
description
- A doc string above the
GraphQL field
definition.
- A doc string above the
comment
- Included in the doc string with the prefix
@comment
.
- Included in the doc string with the prefix
deprecation
- Using the GraphQL
@deprecated
directive.
- Using the GraphQL
datatype
- Using the built-in
scalar
. - Custom
scalar
are also provided to cover other datatypes.
- Using the built-in
unit
- Used as an attribute in a particular
GraphQL field
- Used as an attribute in a particular
min
- Added as info to the doc string
@min:
.
- Added as info to the doc string
max
- Added as info to the doc string
@max:
.
- Added as info to the doc string
allowed
- A
GraphQL Enum
is created to hold the set of possible values expected for thatGraphQL Field
- A
default
- Added as info to the doc string as
@default:
.
- Added as info to the doc string as
Considering the Position
and Switch
properties of the Row1.DriverSide.Window
, its specification looks like:
Vehicle.Cabin.Door.Row1.DriverSide.Window.Position:
comment: Relationship between Open/Close and Start/End position is item dependent.
datatype: uint8
description: Item position. 0 = Start position 100 = End position.
max: 100
min: 0
type: actuator
unit: percent
Vehicle.Cabin.Door.Row1.DriverSide.Window.Switch:
allowed:
- INACTIVE
- CLOSE
- OPEN
- ONE_SHOT_CLOSE
- ONE_SHOT_OPEN
datatype: string
description: Switch controlling sliding action such as window, sunroof, or blind.
type: actuator
"""Door window status. Start position for Window is Closed."""
type Window {
"""
Item position. 0 = Start position 100 = End position.
@comment: Relationship between Open/Close and Start/End position is item dependent.
@min: 0
@max: 100
"""
position(unit: RelationUnit = PERCENT): UInt8
"""
Switch controlling sliding action such as window, sunroof, or blind.
"""
switch: WindowSwitchEnum
}
enum WindowSwitchEnum {
INACTIVE
CLOSE
OPEN
ONE_SHOT_CLOSE
ONE_SHOT_OPEN
}
The exporter has the option to save the mapping references to a .json
file by using the --legacy-mapping-output
. For example:
vspec export graphql --vspec path_to_spec.vspec --output path_to_output_schema.graphql --legacy-mapping-output path_to_mapping_file.json
The mapping reference file will look like follows:
{
"quantity_kinds_and_units": {
"info": "Mappings of vspec quantity kind and their units to the corresponding names in GraphQL.",
"mappings": {
"acceleration": {
"gql_unit_enum": "AccelerationUnit_Enum",
"units": {
"centimeters per second squared": "CENTIMETERS_PER_SECOND_SQUARED",
"meters per second squared": "METERS_PER_SECOND_SQUARED"
}
},
...
},
},
"vspec_branches": {
"info": "Mappings of vspec branches to the corresponding names in GraphQL.",
"mappings": {
"Vehicle.Body.Lights.Beam": {
"gql_type": "Vehicle_Body_Lights_Beam",
"gql_instance_enum": "Vehicle_Body_Lights_Beam_Instance_Enum",
"instance_labels": {
"Low": "LOW",
"High": "HIGH"
}
},
...
},
},
"vspec_leaves": {
"info": "Mappings of vspec leaves to the corresponding names in GraphQL.",
"mappings": {
"Vehicle.ADAS.ActiveAutonomyLevel": {
"gql_field": "activeAutonomyLevel",
"in_gql_type": "Vehicle_ADAS",
"gql_allowed_enum": "Vehicle_ADAS_ActiveAutonomyLevel_Enum",
"allowed_values": {
"SAE_0": "SAE_0",
"SAE_1": "SAE_1",
"SAE_2_DISENGAGING": "SAE_2_DISENGAGING",
"SAE_2": "SAE_2",
"SAE_3_DISENGAGING": "SAE_3_DISENGAGING",
"SAE_3": "SAE_3",
"SAE_4_DISENGAGING": "SAE_4_DISENGAGING",
"SAE_4": "SAE_4",
"SAE_5_DISENGAGING": "SAE_5_DISENGAGING",
"SAE_5": "SAE_5"
}
},
...
}