This document, the Gen2 TRANSPORT specification, describes the Gen2 transport protocols, and the mapping of the message layer on these transports. The companion specification Gen2 CORE describes the messaging layer.
This is required.
This document describes the transport bindings of the Vehicle Service Interface. The split between transport bindings and messaging layer specifications improves readability and simplify extending Gen2 to further transports in the future. The Gen2 supports multiple transport bindings, namely HTTPS and secure WebSockets.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY, MUST, and SHALL are to be interpreted as described in [RFC2119].
This specification defines conformance criteria that apply to a single product: specifically the 'Vehicle API' Gen2 that implements the interfaces, semantics and behaviour defined in this document.
The acronym 'Gen2' is used to refer to this document, the 'Gen2' specification. The acronym 'VSS' is used to refer to the 'Vehicle Signal Specification' which is defined by the GENIVI Alliance. The term 'WebSocket' when used in this document, is as defined in the W3C WebSocket API and the WebSocket Protocol.
This chapter defines features that SHALL be common for all transport protocols.
The server implementation SHALL support at least the error numbers and reasons listed in the table below.
The client SHOULD support any status code defined in [RFC2616].
Error Number (Code) | Error Reason | Error Message |
---|---|---|
304 (Not Modified) | not_modified | No changes have been made by the server. |
400 (Bad Request) | bad_request | The server is unable to fulfil the client request because the request is malformed. |
400 (Bad Request) | filter_invalid | Filter requested on non-primitive type. |
401 (Unauthorized) | user_token_expired | User token has expired. |
401 (Unauthorized) | user_token_invalid | User token is invalid. |
401 (Unauthorized) | user_token_missing | User token is missing. |
401 (Unauthorized) | device_token_expired | Device token has expired. |
401 (Unauthorized) | device_token_invalid | Device token is invalid. |
401 (Unauthorized) | device_token_missing | Device token is missing. |
401 (Unauthorized) | too_many_attempts | The client has failed to authenticate too many times. |
401 (Unauthorized) | read_only | The desired signal cannot be set since it is a read only signal. |
403 (Forbidden) | user_forbidden | The user is not permitted to access the requested resource. Retrying does not help. |
403 (Forbidden) | user_unknown | The user is unknown. Retrying does not help. |
403 (Forbidden) | device_forbidden | The device is not permitted to access the requested resource. Retrying does not help. |
403 (Forbidden) | device_unknown | The device is unknown. Retrying does not help. |
404 (Not Found) | invalid_path | The specified data path does not exist. |
404 (Not Found) | private_path | The specified data path is private and the request is not authorized to access signals on this path. |
404 (Not Found) | invalid_subscriptionId | The specified subscription was not found. |
406 (Not Acceptable) | not_acceptable | The server is unable to generate content that is acceptable to the client |
429 (Too Many Requests) | too_many_requests | The client has sent the server too many requests in a given amount of time. |
502 (Bad Gateway) | bad_gateway | The server was acting as a gateway or proxy and received an invalid response from an upstream server. |
503 (Service Unavailable) | service_unavailable | The server is currently unable to handle the request due to a temporary overload or scheduled maintenance (which may be alleviated after some delay). |
504 (Gateway Timeout) | gateway_timeout | The server did not receive a timely response from an upstream server it needed to access in order to complete the request. |
The payload SHALL have JSON format. See for the payload format of the messages for the different transport protocols.
Clients must provide a token to the server in order to verify that it is correctly authorized for the service it requests (c.f. CORE document).Tokens are integrated in HTTP requests in the Authorization
header. For WebSockets requests an optional authorization
property in the payload can be used.
The transport protocols supported are the secure versions of HTTP and WebSockets. Further transport protocols may be supported in future versions of this specification.
The message data components described in the CORE document are in the first hand mapped to required HTTP parameters, and only when there is no appropriate mapping it is mapped to the payload. The subscribe/unsubscribe messages are not supported by this transport protocol.
N/A?
N/A?
The client MAY send a HTTPS GET request message to the server to get the value of one or more vehicle signals. If the server is able to satisfy the request it SHALL return a response containing the requested value(s). If the server is unable to fulfil the request, e.g. because the client is not authorized to retrieve one or more of the signals, then the server response SHALL have the status code set to indicate error.
Example:
Request:
GET Vehicle/Drivetrain/InternalCombustionEngine/RPM HTTP/1.1
Host: 127.0.0.1:1337
Connection: keep-alive
Accept: application/json
User-Agent: Chrome/34.0.1847.137 Safari/537.36
Accept-Encoding: gzip,deflate
Accept-Language: en-US,en;q=0.8,de;q=0.6
Successful response:
HTTP/1.1 200 OK
X-Powered-By: Express
Vary: Accept-Encoding
Content-Type: application/json; charset=utf-8
ETag: "-32550834"
Content-Encoding: gzip
Date: Tue, 13 Jun 2014 19:47:27 GMT
Connection: keep-alive
Transfer-Encoding: chunked
{
"value": "2372",}
"timestamp": 1489985044000
{"message": "No match for path in tree."}}
JWT tokens will be sent in the Authorization
header, following with term Bearer
and a space character.
The following example assumes eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UifQ.xuEv8qrfXu424LZk8bVgr9MQJUIrp1rHcPyZw_KSsds
is the actual token:
GET /Vehicle/Drivetrain/InternalCombustionEngine/RPM/ HTTP/1.1
Host: 127.0.0.1:1337
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UifQ.xuEv8qrfXu424LZk8bVgr9MQJUIrp1rHcPyZw_KSsds
Example:
Request:
GET Vehicle/Drivetrain/FuelSystem?$spec=0 HTTP/1.1
Host: 127.0.0.1:1337
Connection: keep-alive
Accept: application/json
User-Agent: Chrome/34.0.1847.137 Safari/537.36
Accept-Encoding: gzip,deflate
Accept-Language: en-US,en;q=0.8,de;q=0.6
Response:
HTTP/1.1 200 OK
X-Powered-By: Express
Vary: Accept-Encoding
Content-Type: application/json; charset=utf-8
ETag: "-32550834"
Content-Encoding: gzip
Date: Tue, 13 Jun 2014 19:47:27 GMT
Connection: keep-alive
Transfer-Encoding: chunked
{
"metadata": {"FuelSystem":{"type":"branch","description":"Fuel system data.","children":{"HybridType, ... }}}}
"timestamp": 1489985044000
Example:
Request:
GET Vehicle/Cabin/Door?$path=*.*.IsOpen HTTP/1.1
Host: 127.0.0.1:1337
Connection: keep-alive
Accept: application/json
User-Agent: Chrome/34.0.1847.137 Safari/537.36
Accept-Encoding: gzip,deflate
Accept-Language: en-US,en;q=0.8,de;q=0.6
Response:
HTTP/1.1 200 OK
X-Powered-By: Express
Vary: Accept-Encoding
Content-Type: application/json; charset=utf-8
ETag: "-32550834"
Content-Encoding: gzip
Date: Tue, 13 Jun 2014 19:47:27 GMT
Connection: keep-alive
Transfer-Encoding: chunked
{
"value": {{"path":"Vehicle.Cabin.Door.Row1.Left.IsOpen", "value":"false"},..., {"path":"Vehicle.Cabin.Door.Row4.Right.IsOpen","value":"true"}}}
"timestamp": 1489985044000
The client may request that the server sets the value of one or more signals e.g. to lock one or more doors or open a window by sending an HTTPS POST request to the server. If the server is able to satisfy the request its response SHALL have a 200 OK status code set. If an error occurs e.g. because the client is not authorized to set the requested value, or the value is read-only, the server response SHALL have the status code set to indicate error.
Example:
POST /Vehicle/Drivetrain/Transmission/PerformanceMode HTTP/1.1
Host: 127.0.0.1:9000
Connection: keep-alive
Accept: application/json
User-Agent: Chrome/34.0.1847.137 Safari/537.36
Accept-Encoding: gzip,deflate
Accept-Language: en-US,en;q=0.8,de;q=0.6
{
"value": "sport",}
"timestamp": 1489985044000}
JWT tokens will be sent in the Authorization
header, following with term Bearer
and a space character.
The following example assumes eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UifQ.xuEv8qrfXu424LZk8bVgr9MQJUIrp1rHcPyZw_KSsds
is the actual token:
POST /Vehicle/Drivetrain/Transmission/PerformanceMode/ HTTP/1.1
Host: 127.0.0.1:1337
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UifQ.xuEv8qrfXu424LZk8bVgr9MQJUIrp1rHcPyZw_KSsds
{
"value": "sport",
}
As the WebSocket protocol does not implicitly provide a logical association between the request and response messages described here a key-value pair with the keyname "requestId" is added to the data components described in the CORE document. As the WebSockets protocol neither specifies a set of explicit methods, another key-value pair with the keyname "action" is also added. See for the declaration of these new key-value pairs. All data components are mapped to the payload.
If the client application is an HTML Application running in a web runtime or is a web page running in a browser, the WebSocket instance may either be instantiated natively or be created using a 'standards compliant' WebSocket JavaScript library.
A WebSocket can also be initiated from a native (e.g. C++) Application or from an Application written using a 'Managed Runtime' language like Java or C#. It is assumed that native and managed clients use a suitable standards compliant WebSocket library to request that a WebSocket connection is opened on the server.
Implementations that support additional devices or multiple Gen2 services should provide discovery. Alternatively, the location of a particular VIS Server instance on the local vehicle network may be handled by configuration, either as part of a package manifest or by consulting a registry on application install. The 'wwwgen2' hostname in this specification is used an example.
A client running on the vehicle is able to connect to the Gen2 Server instance using the hostname e.g. 'wwwgen2' and uses the default port 443. The hostname 'wwwgen2' may locally be mapped to the localhost IP address 127.0.0.1 e.g. by adding an entry to the /etc/hosts file.
The sub-protocol name SHALL be 'wvss' with a version number suffix, e.g. wvss2.0. The sub-protocol version will be associated with exactly one Vehicle Server Specification (VSS) version so that the client and server can correctly validate and parse request and response message packets.
var vehicle = new WebSocket("wss://wwwgen2", "wvss2.0");
The client SHALL connect to the server over HTTPS and request that the server opens a WebSocket. All WebSocket communications between the client and server MUST be over ‘wss’. Non encrypted communication is not supported, hence the server MUST refuse ‘ws’ connection requests.
This specification assumes that a single WebSocket is used to enable communication between a client application and the server. It is not explicitly prohibited for the client to request that the server opens more than one WebSocket, however, the server MAY refuse to open a subsequent WebSocket connection and the client is responsible for handling this gracefully.
If more than one WebSocket connection is established between a client application and the server then each connection MUST be managed independently. For example, subscriptions created using a particular WebSocket connection shall only trigger notifications via that connection and the client MUST use that WebSocket connection to unsubscribe.
If more than one WebSocket connection has been established between one or more clients and a particular server instance, there is a risk that race conditions and concurrency issues could occur. An example of this would be where two or more WebSocket connections are used to update a particular setting at the same time.
Unless explicitly stated otherwise, the client MAY only assume that the server implements a simple concurrency model where lost updates and dirty reads could potentially occur if the server has more than one WebSocket connection open.
The WebSocket may be closed by either the client or the server by invoking the ‘close()’ method on the WebSocket instance.
The following example shows the lifetime of a WebSocket on the client:
// Open the WebSocket
var vehicle = new WebSocket("wss://localhost:4343", "wvss2.0");
// WebSocket is used to GET, SET, SUBSCRIBE and UNSUBSCRIBE
…
// Close the WebSocket
vehicle.close();
The Gen2 Server may terminate the WebSocket connection if it has not received a request for a period determined by the server. It is the client’s responsibility to handle this gracefully and to recover and request new subscriptions, where required.
The client MAY send a getRequest message to the server to get the value of one or more vehicle signals. If the server is able to satisfy the request it SHALL return a getSuccessResponse message. If the server is unable to fulfil the request, e.g. because the client is not authorized to retrieve one or more of the signals, then the server SHALL return a getErrorResponse message. The structure of these message objects is defined below.
Object Name | Attribute | Type | Required |
---|---|---|---|
getRequest | |||
action | Action | Yes | |
path | string | Yes | |
authorization | string | Optional | |
requestId | string | Yes |
Object Name | Attribute | Type | Required |
---|---|---|---|
getSuccessResponse | |||
action | Action | Yes | |
requestId | string | Yes | |
value | object | Yes | |
timestamp | integer | Yes |
In the table above the value attribute has the type object as it may contain multiple values, each associated to other attributes. However, an atomic value representation MUST be of type string.
Object Name | Attribute | Type | Required |
---|---|---|---|
getErrorResponse | |||
action | Action | Yes | |
requestId | string | Yes | |
error | Error | Yes | |
timestamp | integer | Yes |
Example:
Request:
{
"action": "get",}
"path": "Vehicle/Drivetrain/InternalCombustionEngine/RPM",
"requestId": "8756"
"action": "get",}
"requestId": "8756",
"value": "2372",
"timestamp": 1489985044000
"action": "get",}
"requestId": "8756",
"error": {"number": 404, "reason": "Not found", "message": "No match for path in tree."},
"timestamp": 1489985044000
In the case a VSS node that is addressed by the path contains access control metadata, then the request must contain the field "authorization" with its value being a JWT token. The token validation must be successful for a GetSuccessResponse to be returned, else a GetErrorResponse is returned.
Example:
Request:
{
"action": "get",}
"path": "Vehicle/Drivetrain/InternalCombustionEngine/RPM",
"authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1...Zw_KSsds"
"requestId": "8657"
"action": "get",}
"requestId": "8657",
"value": "2372",
"timestamp": 1489985044000
A client may issue a service discovery read request to access the metadata defining the nodes in the VSS tree. A successful response will contain the metadata from all nodes of the subtree defined by the subtree root node that is addressed by the path. The service discovery read request MUST contain a query component with the reserved word "$spec", and an associated integer value (c.f. CORE spec, "Filtering" chapter).
Example:
Request:
{
"action": "get",}
"path": "Vehicle/Drivetrain/FuelSystem?$spec=0",
"requestId": "5687"
"action": "get",}
"requestId": "5687",
"metadata": {"FuelSystem":{"type":"branch","description":"Fuel system data.","children":{"HybridType, ... }}}
"timestamp": 1489985044000
A client may issue a search read request to access multiple values in one request message. A successful response will contain the values from all nodes matching the path concatenated with $path value (a delimiter is automatically inserted). The search read request MUST contain a query component with the reserved word "$path", and an associated extension to the path (c.f. CORE spec, "Filtering" chapter).
Example:
Request:
{
"action": "get",}
"path": "Vehicle/Cabin/Door?$path=*.*.IsOpen",
"requestId": "5688"
"action": "get",}
"value": {{"path":"Vehicle.Cabin.Door.Row1.Left.IsOpen", "value":"false"},..., {"path":"Vehicle.Cabin.Door.Row4.Right.IsOpen","value":"true"}},
"requestId": "5688",
"timestamp": 1489985044000
The client may request that the server sets the value of one or more signals e.g. to lock one or more doors or open a window by sending a setRequest message to the server. If the server is able to satisfy the request it SHALL return a setSuccessResponse message. If an error occurs e.g. because the client is not authorized to set the requested value, or the value is read-only, the server SHALL return a setErrorResponse message.
Object Name | Attribute | Type | Required |
---|---|---|---|
setRequest | |||
action | Action | Yes | |
path | string | Yes | |
value | string | Yes | |
authorization | string | Optional | |
requestId | string | Yes |
Object Name | Attribute | Type | Required |
---|---|---|---|
setSuccessResponse | |||
action | Action | Yes | |
requestId | string | Yes | |
timestamp | integer | Yes |
Object Name | Attribute | Type | Required |
---|---|---|---|
setErrorResponse | |||
action | Action | Yes | |
requestId | string | Yes | |
error | Error | Yes | |
timestamp | integer | Yes |
Example:
Request:
{
"action": "set",}
"path": "Vehicle/Drivetrain/Transmission/PerformanceMode",
"value": "sport",
"requestId": "5687"
"action": "set",}
"requestId": "5687",
"timestamp": 1489985044000
"action": "set",}
"requestId": "5687",
"error": {"number": 404, "reason": "Not found", "message": "No match for path in tree."},
"timestamp": 1489985044000
In the case a VSS node that is addressed by the path contains access control metadata, then the request must contain the field "authorization" with its value being a JWT token. The token validation must be successful for a setSuccessResponse to be returned, else a setErrorResponse is returned.
Example:
Request:
{
"action": "set",}
"path": "Vehicle/Drivetrain/Transmission/PerformanceMode",
"value": "sport",
"authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1...Zw_KSsds"
"requestId": "5687"
"action": "set",}
"requestId": "5687",
"timestamp": 1489985044000
The client may send a subscribeRequest message to request a subscription to one or more signals, thereby requesting the server to repeatedly return subscription notification messages, as specified by the "filter" query (c.f. CORE, "Filtering" chapter). The server MAY reduce the number of subcriptionNotification messages sent to the client in order to reduce processing demands, particularly when the client has subscribed to continuously varying signals. If the server is able to satisfy the request it SHALL return a subscribeSuccessResponse message. If an error occurs e.g. because the client is not authorized to set the requested value, the server SHALL return a subscribeErrorResponse message.
Object Name | Attribute | Type | Required |
---|---|---|---|
subscribeRequest | |||
action | Action | Yes | |
path | string | Yes | |
filter | string | Optional | |
authorization | string | Optional | |
requestId | string | Yes |
Object Name | Attribute | Type | Required |
---|---|---|---|
subscribeSuccessResponse | |||
action | Action | Yes | |
requestId | string | Yes | |
subscriptionId | string | Yes | |
timestamp | integer | Yes |
Object Name | Attribute | Type | Required |
---|---|---|---|
subscribeErrorResponse | |||
action | Action | Yes | |
requestId | string | Yes | |
error | Error | Yes | |
timestamp | integer | Yes |
Object Name | Attribute | Type | Required |
---|---|---|---|
subscriptionNotification | |||
action | Action | Yes | |
subscriptionId | string | Yes | |
value | any | Yes | |
timestamp | integer | Yes |
Example:
Request:
{
"action": "subscribe",}
"path": "Vehicle/Drivetrain/FuelSystem/Level",
"filter": "$intervalEQ2"
"requestId": "6578"
"action": "subscribe",
"subscriptionId": "12345",
"requestId": "6578",
"timestamp": 1489985044000
"action": "subscribe",}
"requestId": "6578",
"error": {"number": 404, "reason": "Not found", "message": "No match for path in tree."},
"timestamp": 1489985044000
"action": "subscription",
"subscriptionId": "12345",
"value": "50",
"timestamp": 1489985044000
In the case a VSS node that is addressed by the path contains access control metadata, then the request must contain the field "authorization" with its value being a JWT token. The token validation must be successful for a subscribeSuccessResponse to be returned, else a subscribeErrorResponse is returned.
Example:
Request:
{
"action": "subscribe",}
"path": "Vehicle/Drivetrain/FuelSystem/Level",
"filter": "$rangeGT5AND$rangeLT10"
"authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1...Zw_KSsds"
"requestId": "6578"
"action": "subscribe",
"subscriptionId": "12345",
"requestId": "6578",
"timestamp": 1489985044000
"action": "subscription",
"subscriptionId": "12345",
"value": "50",
"timestamp": 1489985044000
To unsubscribe from a subscription, the client SHALL send an unsubscribeRequest message to the server. If the server is able to satisfy the request it returns an unsubscribeSuccessResponse message. If an error occurs, for example because an invalid subscriptionId is passed to the server, an unsubscribeErrorResponse message is returned.
If the client has created more than one WebSocket instance, it MUST always unsubscribe using the same WebSocket instance that was originally used to create the subscription.
Object Name | Attribute | Type | Required |
---|---|---|---|
unsubscribeRequest | |||
action | Action | Yes | |
subscriptionId | string | Yes | |
requestId | string | Yes |
Object Name | Attribute | Type | Required |
---|---|---|---|
unsubscribeSuccessResponse | |||
action | Action | Yes | |
subscriptionId | string | Yes | |
requestId | string | Yes | |
timestamp | integer | Yes |
Object Name | Attribute | Type | Required |
---|---|---|---|
unsubscribeErrorResponse | |||
action | Action | Yes | |
subscriptionId | string | Yes | |
requestId | string | Yes | |
error | Error | Yes | |
timestamp | integer | Yes |
Example:
Request:
{
"action": "unsubscribe",}
"subscriptionId": "12345",
"requestId": "5786"
"action": "unsubscribe",}
"subscriptionId": "12345",
"requestId": "5786",
"timestamp": 1489985044000
"action": "unsubscribe",}
"requestId": "6578",
"error": {"number": 404, "reason": "Not found", "message": "No matching subscription Id."},
"timestamp": 1489985044000
Attribute | Type | Description |
---|---|---|
action | Action | The type of action requested by the client or delivered by the server. |
path | String | The path to the desired vehicle signal(s), as defined by the Vehicle Signal Specification (VSS). |
requestId | String | Unique id value specified by the client. Returned by the server in the response and used by the client to link the request and response messages. The value MAY be an integer or a Universally Unique Identifier (UUID). |
subscriptionId | String | Value returned by the server to uniquely identify each subscription. The value MAY be an integer or a Universally Unique Identifier (UUID). |
authorization | string | A JWT formatted security token. |
timestamp | integer | The Coordinated Universal Time (UTC) time that the server returned the response (expressed as number of milliseconds). |
value | string or object | The data value returned by the server. This could either be a string (when single value), or a complex type comprised of nested name/value pairs in JSON format(when multiple values). |
filter | string | Provides a filtering mechanism to reduce the demands of a subscription on the server. Query format, see CORE:Filtering chapter. |
metadata | object | Metadata describing the potentially available signal (sub)tree. |
error | Error | Returns an error code, reason and message. |
The payload that is sent over the supported transport protocols SHALL use the JSON definitions in this appendix, unless otherwise specified in the Gen2 TRANSPORT specification.
The definitions within this section describe the datatypes referenced within the JSON Schema for the Gen2 WebSocket interfaces, and for the Gen2 HTTP payloads.
{
"definitions": {
"action": {
"enum": [ "get", "set", "subscribe", "subscription", "unsubscribe"],
"description": "The type of action requested by the client and/or delivered by the server",
},
"requestId": {
"description": "Returned by the server in the response and used by the client to link the request and response messages.",
"type": "string"
},
"path": {
"description": "The path to the desired vehicle signal(s), as defined by the metadata schema.",
"type": "string"
},
"value": {
"description": "The data value returned by the server. This could either be a basic type, or a complex type comprised of nested name/value pairs in JSON format.",
"type": "string"
},
"timestamp": {
"description": "The Coordinated Universal Time (UTC) time that the server returned the response (expressed as number of milliseconds).",
"type": "integer"
},
"filter": {
"description": "May be specified in order to throttle the demands of subscriptions on the server. C.f. CORE:Filtering chapter",
"type": "string"
},
"subscriptionId":{
"description": "Integer handle value which is used to uniquely identify the subscription.",
"type": "string"
},
"metadata":{
"description": "Metadata describing the potentially available signal tree.",
"type": "object"
},
"error": {
"description": "Server response for error cases",
"type": "object",
"properties": {
"number": {
"description": "HTTP Status Code Number",
"type": "integer"
},
"reason": {
"description": "Pre-defined string value that can be used to distinguish between errors that have the same code",
"type": "string"
},
"message": {
"description": "Message text describing the cause in more detail",
"type": "string"
}
}
}
}
}
The Action enumeration is used to define the type of action requested by the client. All client messages MUST contain a JSON structure that has an action name/value pair and the value of the action property MUST be one of the values specified in the enumeration:
Object Name | Attribute | Type | Required |
---|---|---|---|
Error | |||
number | integer | Yes | |
reason | string | Yes | |
message | string | Yes |
Diagram showing xxx.