Vehicle Signal Server Information Service Specification

W3C First Public Working Draft 20 October 2016 Candidate Recommendation

This version:
https://www.w3.org/TR/2016/WD-vehicle-information-service-20161020/ https://www.w3.org/TR/2018/CR-vehicle-information-service-20180205/
Latest published version:
https://www.w3.org/TR/vehicle-information-service/
Latest editor's draft:
https://w3c.github.io/automotive/vehicle_data/vehicle_information_service.html
Editors: Implementation report:
https://w3c.github.io/automotive/vehicle_data/viss_implementations.html
Previous version:
https://www.w3.org/TR/2016/WD-vehicle-information-service-20161020/
Editors:
Kevin Gavigan , Jaguar Land Rover
Adam Crofts , Jaguar Land Rover
이원석(Wonsuk Lee) , 한국전자통신연구원(ETRI)
Powell Kinney , Vinli
Repository and Participation:
We are on github.
File a bug/issue.
Commit history.
Mailing list archive.

Abstract

The W3C Vehicle Signal Server Specification This specification defines a WebSocket based API that enables for a Vehicle Information Service (VIS) to enable client applications to GET, SET, SUBSCRIBE get, set, subscribe and UNSUBSCRIBE unsubscribe to vehicle signals and data attributes.

The purpose of the specification is to promote a Server API that enables application development in a consistent manner across participating automotive manufacturers.

It is recommended that this Vehicle Signal Server Specification (VSSS) is read in conjunction with the W3C Vehicle Signal Client Specification (VSCS) and the GENIVI Vehicle Signal Specification (VSS). The Vehicle Signal Client Specification defines an API that wraps the data access and security primitives defined in this Server Specification. It has been defined to support the development of 'standards-compliant' JavaScript libraries that can be used by web based clients. It is assumed that native clients (written for example in C/C++) and managed runtime clients (written in languages like Java or C#) invoke the WebSocket Server API using standard WebSocket libraries that have been created specifically for those languages. The GENIVI Vehicle Signal Specification (VSS) defines the set of vehicle signals and data that are exposed via this Server Specification. The term 'signal' is used here to represent an item of data that can vary over time, for example vehicle speed, whilst the term 'static data' is used to denote a temporally unchanging property like vehicle width. This Server Specification describes a discovery mechanism that defines the set of signals and data that a particular client can access at a particular point in time. It is recognized that some automobile manufacturers may expose more signals and data than others. The Vehicle Signal Specification supports both extensibility and the ability to define private branches. In addition, the 'tree' of signals that is accessible at any point in time may also vary depending on standard access control principles. That is, it can vary based on the identity of the user (person or organisation) requesting the data and/or the device (e.g. vehicle) where the request originates. To support this, the Server Specification describes a token based mechanism that can optionally be used to pass tokens to the WebSocket Server to represent the user of an application and the device that the application is running on. The target platform supported by the specification is exclusively passenger vehicles. Use of this specification for non-passenger applications (for example heavy machinery, marine and airline infotainment) is not prohibited, but is not covered in the design or content of the API and therefore may be insufficient. An example use case could be the implementation of a 'Home Mechanic' application that provides warnings if any the following need attention: tire pressure, engine oil level, washer fluid level and battery charge level. Future use case innovations in transportation, safety, navigation, smart energy grids, smart transportation, consumer infotainment and personalisation are all possible through this specification. Web developers building interoperable applications based upon this API, will help empower a common web platform across consumer devices and passenger vehicles within the Web of Things.

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.

This document was published by the Automotive Working Group as a First Public Working Draft. Candidate Recommendation. This document is intended to become a W3C Recommendation. If you wish to make comments Comments regarding this document, please document are welcome. Please send them to public-automotive@w3.org ( subscribe , archives ). All comments are welcome. W3C publishes a Candidate Recommendation to indicate that the document is believed to be stable and to encourage implementation by the developer community. This Candidate Recommendation is expected to advance to Proposed Recommendation no earlier than 08 March 2018.

Please see the Working Group's implementation report .

Publication as a First Public Working Draft Candidate Recommendation does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy . W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy .

This document is governed by the 1 September 2015 February 2018 W3C Process Document .

1. Introduction

The vehicle SHALL This section is non-normative.

This specification describes how a vehicle can expose vehicle signals and static data via a WebSocket. This enables a client to GET or SET vehicle signals and data; to SUBSCRIBE to receive notifications and to UNSUBSCRIBE from receiving notifications.

A future revision of this specification may consider additionally exposing The API that is used to manage access to vehicle signals via a RESTful web service but this and static data is out of scope for defined in this version of Vehicle Information Service Specification (VISS). The VISS also describes a discovery mechanism that defines the specification. set of signals and data that a client can access at a particular point in time.

The W3C WebSocket API term 'signal' is defined used here and to represent an item of data that can vary over time, for example vehicle speed, whilst the WebSocket Protocol expression 'static data' is defined in RFC6455 . used to denote a temporally invariant property like vehicle width.

A component or vehicle-based software module running on may implement the vehicle is required to create interface and behaviours defined in this specification by creating a WebSocket and listen server instance that listens for an inbound connections connection request from application clients a client in order to enable secure access to vehicle signals. In this specification this module are is referred to as the ‘WebSocket Vehicle Signal Server’ (WVSS) VIS Server or for simplicity as ‘the server’. just 'the server'.

This specification assumes that The Vehicle Information Service Specification (VISS) defines a single WebSocket is used number of methods for accessing vehicle data which are strictly agnostic to enable communication between the client application data model. Any data model where data and signals can be specified using a string could potentially be supported. However this version of the server in order to reduce processing overhead. It is not explicitly prohibited for the client to request specification specifies that the server opens more than one WebSocket. However, data model is the server MAY refuse to open a subsequent WebSocket connection GENIVI Vehicle Signal Specification [ VSS ]. The VSS supports both extensibility and the client is responsible ability to define private branches and will be used for handling each of the examples within this gracefully. specification.

If more than one WebSocket connection is established between a Client Application and the server then each connection is managed independently. For example, subscriptions created using a particular WebSocket connection only trigger notifications via that connection and In addition, the client must use 'tree' of signals that WebSocket instance 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 accessible at any point in time may also vary depending on standard access control principles. That is, it can vary based on the identity of this would be, where two the user (person or more WebSocket connections are used to update a particular setting at organisation) requesting the same time. data and/or the application or device (e.g. vehicle) where the request originates.

Unless explicitly stated otherwise, To support this, the client Service Specification describes an extensible token based security mechanism that can only assume optionally be used to pass tokens to the VIS Server, for example to represent the user of an application and/or the device that the server implements client application is running on.

A future revision of this specification may consider additionally exposing vehicle signals via a simple concurrency model where lost updates and dirty reads could potentially occur if RESTful web service but this is out of scope for this version of the server has more than one WebSocket connection open. specification.

The following example illustrates how a client could invoke the API. This simplified example is for illustrative purposes only, it does not show error handling and is not intended to be commercial code.

Example 1
// open WebSocket var vehicle = new WebSocket();
// Open the WebSocket
var vehicle  = new WebSocket("wss://wwwivi", "wvss1.0");
// establish authorization
vehicle.onopen =  () {
  vehicle.send('{"action": "authorize",
    "tokens": {"authorization": "<user_token_value>"},
    "requestId": 103}');

// Establish authorization
vehicle.onopen = function () {
  vehicle.send('{"action": "authorize", "tokens": {"authorization": "user_token_value"}, "requestId": "103"}');

};
// request a signal
 (vehicle.readyState === OPEN) {
  vehicle.send();

// Message response handler for all possible actions
vehicle.onmessage = function(event){
  var msg = JSON.parse(event.data);  switch(msg.action){    case "authorize":
      authHandler(msg);
      break;    case "getMetadata":
      getMetadataHandler(msg);
      break;    case "get":
      getReqHandler(msg);
      break;    case "set":
      setReqHandler(msg);
      break;    case "subscribe":
      subscriptionSetupHandler(msg);
      break;    case "subscription":
      subscriptionHandler(msg);
      break;    case "unsubscribe":
      unsubscribeHandler(msg, false);
      break;    case "unsubscribeAll":
      unsubscribeHandler(msg, true);
      break;
  }
};

  // process messages from the server
  vehicle.onmessage = function(event){
    var msg = JSON.parse(event.data);
    if(msg.path ==  && msg.value){
      console.log( + msg.value);
    }
  };

// Auth request handler
function authHandler(msg) {
  if(msg.hasOwnProperty("TTL")){
    console.log("authorization successful");
    requestMetadata();
  } else {
    console.log("authorization unsuccessful");
  }

}
// close the WebSocket
vehicle.close();

// Close the WebSocket to end the WebSocket session
function closeSocket(){
  vehicle.close();
}

The following example shows a JavaScript Once the WebSocket connection has been established, the client subscription request is able to retrieve the metadata from the server and response. request signals for the client's current level of authentication.

Example 2
// set a subscription, assuming the same authorization and set up from Example (vehicle.readyState === OPEN) { vehicle.send('{"action": "subscribe", "path": "Signal.Drivetrain.InternalCombustionEngine.RPM", "requestId": 104}'); vehicle.onmessage = function(event){ var msg = JSON.parse(event.data); if(msg.hasOwnProperty(){ console.log( + msg.value);
// Request the entire data model, in this example the data model is defined using GENIVI's VSS
function requestMetadata(){
  vehicle.send('{"action": "getMetadata", "requestId": "103"}');
}
// Request the entire data model and if successful, request a signalfunction getMetadataHandler(msg){  if(msg.hasOwnProperty('metadata')){    console.log("Metadata Received");    console.log("Metadata: " + JSON.stringify(msg.metadata));
    getSignal(msg.metadata, "Signal.Drivetrain.Transmission.Speed");
  } else {
    console.log("getMetadata Error");
  }
}
// Request a signalfunction getSignal(metadata, path){  // A check could be made here to ensure the signal is available within the metadata
  vehicle.send('{"action": "get", "path": ' + path + ', "requestId": "105"}');
}

The client is also able to subscribe to signals if the client's authentication permits access.

Example 3
// Set a subscription, assuming the same authorization and set up from Example 1var rpmSubscriptionId, rpmRequestId = "106";// Set up the subscriptionfunction subscribeToRPMNotifications(){
  vehicle.send('{"action": "subscribe", "path": "Signal.Drivetrain.InternalCombustionEngine.RPM",  "requestId": ' + rpmRequestId + '}');
}
// Handle the subscription responsefunction subscriptionSetupHandler(msg){    if(msg.hasOwnProperty("requestId") && msg.requestId == rpmRequestId){      console.log("Subscription set with a subscription ID of " + msg.subscriptionId);
      rpmSubscriptionId = msg.subscriptionId;
    }
}
// Handle the subscription notificationfunction subscriptionHandler(msg){    if(msg.hasOwnProperty("subscriptionId") && msg.subscriptionId == rpmSubscriptionId){      console.log("The current engine rpm is " + msg.value);
    }
  };

}

The target platform supported by the specification is exclusively passenger vehicles. Use of this specification for non-passenger applications (for example heavy machinery, marine and airline infotainment) is not prohibited, but is not covered in the design or content of the API.

An example use case could be the implementation of a 'Home Mechanic' application that provides warnings if any the following need attention: tire pressure, engine oil level, washer fluid level and battery charge level.

Exposing vehicle signals in a standardized manner facilitates the integration of vehicles within the Web of Things (WoT) and supports future use case innovations in a variety of fields including transportation, safety, navigation, energy management, smart transportation and consumer infotainment.

The data format used for client/server communication within this specification is JSON encoded strings, however other data formats may be supported in future versions of the specification.

2. Conformance

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 'in-vehicle' WebSocket Vehicle Signal Server Information Service that implements the interfaces, semantics and behaviour defined in this document. For simplicity, this usually is referred to as the 'WebSocket Server' or just 'the server'

3. Terminology

The acronym 'VISS' is used to refer to this document, the 'Vehicle Information Service Specification'.

The acronym 'VSS' is used to refer to the 'Vehicle Signal Specification' (see here ) which is defined by the GENIVI Alliance.

The term 'WebSocket' when used in this document, is as defined in the W3C WebSocket API (see here ) and the WebSocket Protocol (see RFC6455 ).

4. Table of Figures

5. Architecture

This section is non-normative.

Introduction

Overview

In a typical vehicle design, signals and data are transmitted between Electronic Control Units (ECUs) connected via internal vehicle networks. These include Controller Area Networks (CAN), Media Oriented Systems Transport (MOST) and Local Interconnect Networks (LIN). ECUs on these networks broadcast messages on network buses, and other ECUs on the bus respond to the messages.

In the component diagram included below, in Figure 2, the internal vehicle CAN, MOST and LIN networks and the ECUs that communicate via these networks are abstracted and for simplicity, represented by the System component.

For safety, security and commercial reasons not all clients should be able to GET, SET or SUBSCRIBE to particular vehicle signals and data attributes. As a consequence, access-control must be managed so clients cannot simply connect directly to ECUs or to CAN, MOST or LIN network buses.

In this specification, the term 'signal' refers to a value that can change over time, for example, vehicle speed, whilst 'static data' or simply 'data' is used for a value that does not change e.g. vehicle length.

The vehicle signals and static data that are available within the vehicle System are exposed in a controlled manner to the Web Socket VIS Server. The interface and communication mechanisms that are used between the vehicle System and the Web Socket VIS Server are outside of the scope of this specification.

Fig. 1 Diagram showing Components that implement the W3C

Vehicle Signal APIs and their clients WebSocket Information Service (VIS) Server

The WebSocket As stated above, the VIS Server is the vehicle 'in-vehicle' system that is responsible for exposing vehicle signals and data to its on-board clients by implementing the interface and behaviours defined in this Vehicle Signal Server Information Service Specification (VSSS) (VISS) .

The WebSocket VIS Server exposes signals and data in a manner that is consistent with the accompanying data model. The data model is not mandated by this specification, however the recommended data model used within this specification is the Vehicle Signal Specification (VSS) . This defines a 'tree-like' logical taxonomy of the vehicle, (formally a Directed Acyclic Graph), where major vehicle structures (e.g. body, engine) are near the top of the tree and the logical assemblies and components that comprise them, are defined as their child nodes. Each of the child nodes in the tree is further decomposed into its logical constituents, and the process is repeated until leaf nodes are reached. A 'leaf node' is a node at the end of a branch that cannot be decomposed because it represents a single signal or data attribute value. An example VSS tree is shown below, its contents are illustrative:

Diagram showing an example Vehicle Signal tree
Fig. Figure 2 1 Diagram showing an example Vehicle Signal Tree

Signals Within GENIVI's VSS data model, signals are named according to their path using the dot notation e.g. engine.rpm. The methods defined within this document support any path notation which can be represented as a string.

The client MAY may invoke the WebSocket Server getVSS VIS Server's getMetadata method to request that the server returns metadata that describes which signals and data attributes could potentially be accessed provided that the user and/or device is suitably authorised. authorized. This and other valid WebSocket VIS Server actions are defined in more detail here .

In-Vehicle Clients

This section is non-normative.

In-vehicle clients include both those clients that are running on an ECU in the vehicle itself, e.g. an ECU that implements an In Vehicle In-Vehicle Infotainment (IVI) system, but also includes clients running on a user's device, e.g. a laptop, phone or tablet, that is connected via the vehicle's WiFi client (if one exists).

Component diagram showing W3C Vehicle Information APIs
Figure 2 Diagram showing Components that implement the W3C Vehicle Information APIs and their clients

The methods defined on the WebSocket VIS Server interface may be invoked by different types of on-board and off-board clients. On-board clients, running on the vehicle fall into one of two major categories:

Applications running in the vehicle that can access vehicle signals and data and have a User Interface that the driver or passengers in the vehicle can interact with.

Agents typically have no user interface. They can also invoke methods exposed on the WebSocket VIS Server but their purpose is to connect to one or more off-board e.g. Vehicle to Everything (V2X) internet Servers in order to send data off-board.

Both applications and agents can be subdivided into those that are web-based and which run in a 'Web Runtime' and are implemented using Web Standards like HTML, CSS and JavaScript; those that run in their own native process written using e.g. C, C++ or Objective-C; and those that run in a Managed Runtime process written using languages like C# or Java.

Web applications and web agents MAY may directly invoke the Vehicle Signal Server Information Service interface exposed by the WebSocker server, but it is expected that they typically access vehicle signals and data via VIS Server or implement a JavaScript Library that implements the W3C Vehicle Signal Client API (TODO Add Link). The Client API defines a standard approach to encapsulate or 'wrap' the W3C Vehicle Server Specification API to make it easier for Web based clients 'wrapper' library to access simplify accessing vehicle signals and data in a controlled way.

Sending Signals and Data off-board

In addition to local, in-vehicle applications and agents, a variety of internet-based clients and servers may be interested in accessing vehicle signals and data. However, when a vehicle is not being used, most electrical systems are shut down in order to maximise maximize battery life. This may include the systems that enable Wireless or Mobile connectivity. Then, when When the vehicle is powered up, various systems start up, including potentially those that provide off-board connectivity and the vehicle typically connects either to a local WiFi network or to a Mobile Network Operator (MNO) and is dynamically be assigned an IP address.

At this point, internet based clients and servers do not know the dynamic IP address that was assigned to a specific vehicle. So normally, a vehicle has to connect to a well known endpoint, generally using a URL to connect to a V2X Server. The vehicle and the internet server typically mutually authenticate and the vehicle 'registers' with the V2X server over an encrypted channel passing it a unique identifier e.g. its Vehicle Identification Number (VIN). From that point on, the V2X server has the IP address that is currently assigned to a vehicle with a particular VIN, and can share this information with other internet based clients and servers, which are then able to send messages to the vehicle.

However, if the vehicle loses connectivity and is dynamically assigned a new IP address, it needs to re-register its new IP address and the new address needs to be communicated to any interested parties. For simplicity, this is not shown in the component diagram, primarily because this connectivity only becomes possible after the vehicle has registered with at least one off-board server (which is shown) but also because these scenarios do not affect the interface and behaviours defined in this WebSocket Server Specification Vehicle Information Service Specification.

The component diagram shows four different types of internet based clients. A user may use a Web Page or a Web Application running on a phone or tablet connected to the vehicle's ethernet network to request access to vehicle signals on a particular vehicle. Alternatively these signals could be accessed using a Native or Managed Runtime Application or via another automated Client System or service e.g. the Traffic Management System in a 'Smart City'.

VIS Server State Diagram

The following diagram shows a number of possible states that the VIS Server could occupy:

State Diagram for VIS Server
Figure 3 State diagram for the VIS Server

The state diagram is for illustrative purposes only and does not assume that the VIS Server is either single or multi-threaded. The implementer of the VIS Server is free to determine it's internal design and implementation, however in normal operation, it is assumed that the server will be able to accept multiple requests in quick succession and that the VIS Server will attempt to process and respond to each request in accordance with the specified API.

6. Security and Privacy Considerations

Introduction

The server VIS Server implementation MAY optionally restrict access to one or more vehicle signals so that they can only be accessed in response to a request from an authorized user and/or device. This could be for a variety of reasons, including safety, privacy or commercial considerations.

Hence, a request to GET, SET, SUBSCRIBE or UNSUBSCRIBE to data may require the client to demonstrate to the server that the request is from one or more suitably authorized Security Principals.

The different types of Security Principal, the approach taken to control access to signals and the importance of data privacy are described in the sections that follow.

Security Principals

The types of security principal include:

Type Description
User A person, system or organisation responsible for making the request e.g. driver, Emergency Services, Smart City Traffic Management System.
Device Vehicle or device where the request originates. Could for example be a user's Consumer Electronics (CE) device connected to the vehicle's WiFi hotspot or another vehicle in a convoy; an Electronic Control Unit (ECU) on the same vehicle or any internet connected system e.g. a Web of Things (WoT) device.

Access Control and Authorization

When a client makes a request to access signal data it is performing the request on behalf of one or more Security Principals, that is, for a particular user and/or vehicle/device.

Access to signals is managed and controlled by the server. The server MAY elect not to enforce access controls on a particular signal or set of signals and to enforce different access controls on other signals.

For each security principal that must be authorised authorized by the server, the client SHALL obtain and pass a security token e.g. an OAuth 2.0 token (see RFC6749 ) to the server using a message containing an 'authorize' action as defined here .

A server implementation MAY require that a request for a particular signal includes a security token for both the user (e.g. driver of the vehicle) and for the device (e.g. the vehicle) that is hosting the client. A request for a different set of vehicle signals MAY require that only the user is authorized or that only the device is authorized to access particular signals.

The client and the server are each individually responsible for implementing security best practice. This includes but is not limited to securely obtaining and verifying tokens (as applicable) and the prevention of replays or spoofing of tokens by malicious actors or agents.

WebSocket Channel Authorization

The client MAY send a message with an 'authorize' action to modify the access-control state of the WebSocket channel. The message structure is defined in detail here .

The following diagram illustrates a scenario where the client requests vehicle speed. In this example scenario, this signal is not under access control and so the server returns a message containing the requested data. The client then requests that the server sets the vehicle trunk status to open and the server demands that the client passes access-control credentials before satisfying the request. The sequence of steps are shown in more detail is illustrated in the diagram below:

WebSocket Security token flow
Fig. Figure 3 4 Diagram showing conceptual WebSocket Security Token flow (data structures are illustrative and logical content has been simplified)
Note TODO: Update diagram to reflect auth token structure and review including other diagrams from Wiki

After receiving a message with an 'authorize' action the server attempts to verify the tokens e.g. by checking with the issuing Security Authority. If all of the tokens that are passed to the server are valid, it returns a success response and all subsequent requests received by the WebSocket instance have elevated access control privileges. Specifically, each of the GET, SET, SUBSCRIBE and UNSUBSCRIBE actions have the access control rights that the server deems to be appropriate for the security principals represented by the token(s).

If the client sends a subsequent 'authorize' message to the server with different token value(s). If one or more of these are invalid, then the server returns an error response and the WebSocket access control status remain unchanged. However, if the new token values are valid, then the server returns a success response and the access control privileges associated with the new token(s) only, applies for all requests from that point.

If the client or the server close the WebSocket connection and a new WebSocket instance is opened, then it is opened without elevated access control privileges.

This server service specification defines a standardized, token based approach for access control that includes specific error responses for common user and device access control scenarios. It is important however, that the security model is extensible. Hence, the server MAY implement any type of token that is consistent with this standardized approach and MAY optionally define additional token(s) for other Security Principal type(s). If this is the case, it is expected that the precise type of security tokens that are supported by a particular server implementation, the format of those tokens and all additional error codes and reasons (e.g. to indicate that an additional token type has expired and needs to be renewed) is defined in the Server's documentation.

Use of Encryption

To support a layered security model and to help establish a 'defence in depth', all vehicle signal and data communications between the client and server MUST be strongly encrypted. This is to make it more difficult for an attacker to eavesdrop or tamper with the security tokens; the request data or the response payload.

One way in which this may be implemented is for the client and the server to use a Public Key Infrastructure (PKI) approach, where the client verifies the server's identity by checking the server's X.509 certificate and the client and the server negotiate to establish a secure Transport Layer Security (TLS) 'tunnel'.

The WebSocket protocol mandates that if a client requests that the server opens a WebSocket connection and the request is received over HTTPS, then the WebSocket is established over TLS, that is, a secure 'wss' connection is created.

Token Renewal

Each security token SHALL have a specified lifetime during which it is valid. If on receiving a request for signals that are subject to access-control, the server determines that the request is unauthorised unauthorized because the token has expired, the server returns SHALL return an error response indicating the fact and the client requests SHALL request a new token from the Security Authority and repeat the request.

If the server returns an error response indicating that the request is forbidden, renewing the security token does not make the request valid. In this case, the client should not repeat the request unless some other change has been made that may mean the request is now valid.

7. Initialisation of the Web Socket WebSocket

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 VIS 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 'wwwivi' hostname in this specification is used an example.

A client running on the vehicle is able to connect to the WebSocket VIS Server instance using the hostname e.g. 'wwwivi' and uses the default port 443. The hostname 'wwwivi' 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 always is SHALL be 'wvss' with a version number suffix, e.g. wvss1.0 ); RESTful web services are out of scope for the first revision of this specification, but could wvss1.0. The sub-protocol version will be considered for addition in a later version. To support ‘defence in depth’ associated with exactly one Vehicle Server Specification (VSS) version so that the client and a layered security approach, connections between clients server can correctly validate and servers are strongly encrypted. This is to make it more difficult for an attacker that has succeeded in installing malicious code on a vehicle to eavesdrop, hijack security tokens or impersonate valid security principals in order to get parse request and set sensitive vehicle signals. response message packets.

         var vehicle  = new WebSocket("wss://wwwivi", "wvss1.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.

For security reasons, clients are not able This specification assumes that a single WebSocket is used to connect directly enable communication between a client application and the server. It is not explicitly prohibited for the client to ECUs or request that the server opens more than one WebSocket, however, the server MAY refuse to CAN, MOST or LIN networks. All access open a subsequent WebSocket connection and the client is via WebSocket. This allows 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 securely control access 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 vehicle signals. 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.

8. Message Structure

The client MUST use the WebSocket send method, defined here , to pass request messages to the server. The message signature SHALL be:

WebSocket.send(request)
               WebSocket.send(request)
        

The request message MUST be comprised of one the request objects defined in this section. The client SHALL receive responses from the server using the WebSocket onmessage method, as follows:

WebSocket.onmessage = { }
               WebSocket.onmessage = function(obj){
                        // process data
                }
        

The message returned by the server MUST be one of the response objects defined in the table below.

Request Objects Response Objects
authorizeRequest authorizeSuccessResponse
authorizeErrorResponse
metadataRequest getRequest metadataSuccessResponse
metadataErrorResponse
getRequest getSuccessResponse getSuccessResponse
getErrorResponse
setRequest setSuccessResponse
setErrorResponse
subscribeRequest subscribeSuccessResponse
subscribeErrorResponse
subscriptionNotification
subscriptionNotificationError
unsubscribeRequest unsubscribeSuccessResponse
unsubscribeErrorResponse
unsubscribeAllRequest unsubscribeAllSuccessResponse
unsubscribeAllErrorResponse

The request and response parameters contain a limited number of attributes, defined in the table below.

Term Definitions

Attribute Type Description
action Action The type of action that the server is requested to perform. by the client or delivered by the server.
path DOMString String The path to the desired vehicle signal(s), as defined by the Vehicle Signal Specification (VSS) .
requestId DOMString String Unique id value specified by the client. Returned by the server in the response and used by client to link the request and response messages. The value MAY be an integer or a Universally Unique Identifier (UUID).
subscriptionId DOMString String Value returned by the server to uniquely identify each subscription. The value MAY be an integer or a Universally Unique Identifier (UUID).
tokens object Structure containing one or more security token (e.g OAuth2) name/value pairs.
timestamp DOMTimestamp integer The Coordinated Universal Time (UTC) time that the server returned the response (expressed as number of milliseconds).
value any 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.
TTL int integer Returns the time to live of the authentication authorization token in milliseconds. seconds.
filters object Provides a filtering mechanism to reduce the demands of a subscription on the server.
error metadata object Metadata describing the potentially available signal tree.
error Error Error Returns an error code, reason and message.

JSON Schema Definitions

The definitions within this section describe the datatypes referenced within the JSON Schema VISS interfaces.


{
    "definitions": {        "action": {            "enum": [ "authorize", "getMetadata", "get", "set", "subscribe", "subscription", "unsubscribe", "unsubscribeAll"],            "description": "The type of action requested by the client 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"
        },
        "filters": {            "description": "May be specified in order to throttle the demands of subscriptions on the server.",            "type": ["object", "null"],            "properties": {                "interval": {                    "description": "The server is requested to provide notifications with a period equal to this field's value.",                    "type": "integer"                   
                },
                "range": {                    "description": "The server is requested to provide notifications only whilst a value is within a given range.",                    "type": "object",                    "properties":{                      "below": {                        "description": "The server is requested to provide notifications when the value is less than or equal to this field's value.",                        "type": "integer"  
                      },
                      "above": {                        "description": "The server is requested to provide notifications when the value is greater than or equal to this field's value.",                        "type": "integer"  
                      }
                    }                   
                },
                "minChange": {                    "description": "The subscription will provide notifications when a value has changed by the amount specified in this field.",                    "type": "integer"                   
                }
            }
        },
        "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"                    
                }
            }   
        }
    }
}

Action

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:

{ "", "", "", "", "", "", "" }; Enumeration description
authorize
Enables client to pass security tokens for Security Principals to the server to support access-control.
getVSS getMetadata
Allows the client to request metadata describing signals and data attributes that are potentially accessible.
get
Enables the client to get a value one or more values once.
set
Enables the client to set a value one or more values once.
subscribe
Enables the client to receive a notification request notifications containing a JSON data structure with values for one or more vehicle signals and/or data attributes. The client requests that it is notified when the signal changes on the server.
subscription
Enables the server to send notifications to the client containing a JSON data structure with values for one or more vehicle signals and/or data attributes.
unsubscribe
Allows the client to notify the server that it should no longer receive notifications based on that subscription.
unsubscribeAll
Allows the client to notify the server that it should no longer receive notifications for any active subscription.

Authorize

To enable access to signals and data attributes that are under access control, the client MAY optionally pass a message with an 'authorize' action to the server. The structure of the message and the associated success and error responses are defined below.

{ };

Authorize Request Properties

The properties and schema for an authorizeRequest is:

Object Name Attribute Type Required
{ }; authorizeRequest { };
action Action Yes
tokens object Yes
requestId string Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Authorize Request",    "description": "Enables the user to set access controls for the vehicle signals",    "type": "object",    "required": ["action", "tokens", "requestId"],    "properties": {        "action": {            "enum": [ "authorize" ],            "description": "The identifier for the authorize request"
        },
        "tokens": {            "description": "Extensible key-value pair token mechanism used for access control",            "type": "object",            "properties": {                "authorization": {                    "description": "The user token, for the user that the client is making requests on behalf of",                    "type": "string"
                },
                "www-vehicle-device": {                    "description": "The device token for the originating device that is making the request to the server",                    "type": "string"
                }
            }
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        }
    }
}

The properties and schema for an authorizeSuccessResponse is:

Object Name Attribute Type Required
authorizeSuccessResponse
action Action Yes
TTL integer Yes
requestId string Yes

    
{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Authorize Success Response",    "description": "The response sent from the server upon a successful authorization request",    "type": "object",    "required": ["action", "TTL", "requestId"],    "properties": {        "action": {            "enum": [ "authorize" ],            "description": "The identifier for the authorize request",
        },
        "TTL": {            "description": "The time to live of the authorization token",            "type": "integer"
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        }
    }
}

The properties and schema for an authorizeErrorResponse is:

Object Name Attribute Type Required
authorizeErrorResponse
action Action Yes
error Error Yes
requestId string Yes

  
{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Authorize Error Response",    "description": "The response sent from the server upon an unsuccessful authorization request",    "type": "object",    "required": ["action", "error", "requestId"],    "properties": {        "action": {            "enum": [ "authorize" ],            "description": "The identifier for the authorize request",
        },
        "error": {            "$ref": "#/definitions/error"
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        }
    }
}

The server SHALL provide support the following security token types and names:

Security Principal Token Name Description
User authorization The user that the client is making requests on behalf of. This MAY be a person e.g. driver or passenger, it MAY be an organisation e.g. Emergency Services or MAY be any other legal entity.
Device www-vehicle-device The originating device that is making the request to the server. This MAY be an ECU in the vehicle that is hosting the WebSocket VIS Server or MAY be a device that is connected to the vehicle via a WiFi hotspot or MAY be any other device.

The 'tokens' JSON fragment MAY contain an 'authorization' structure that contains just a single name/value pair, for example, to pass only the user token. Or it may contain only the 'www-vehicle-device' name/value pair to pass the just the vehicle token; alternatively it MAY include name/value pairs for both the 'authorization' and 'www-vehicle-device' tokens. These alternatives are illustrated in the following example:

Example 3 4
(userTokenOnly){ // Pass user token only vehicle.send('{ "action": "authorize", "tokens": { "authorization": "<user_token_value>" }, "requestId": "<some_unique_value>" }');
if(userTokenOnly){
        // Pass user token only
        vehicle.send('{ "action": "authorize",
                "tokens": { "authorization": "<user_token_value>" },
                "requestId": "<some_unique_value>" }');

}  (deviceTokenOnly) {
  // Pass vehicle/device token only
  vehicle.send('{ "action": "authorize",
    "tokens": { "www-vehicle-device": "<device_token_value>" },
    "requestId": "<some_unique_value>" }');

} else if (deviceTokenOnly) {
        // Pass vehicle/device token only
        vehicle.send('{ "action": "authorize",
                "tokens": { "www-vehicle-device": "<device_token_value>" },
                "requestId": "<some_unique_value>" }');

}  (userAndDeviceToken) {
  // Pass tokens for user and device
  vehicle.send('{ "action": "authorize",
    "tokens": { "authorization": "<user_token_value>",
      "www-vehicle-device": "<device_token_value>" },
    "requestId": "<some_unique_value>" }');

} else if (userAndDeviceToken) {
        // Pass tokens for user and device
        vehicle.send('{ "action": "authorize",
                "tokens": { "authorization": "<user_token_value>",
                        "www-vehicle-device": "<device_token_value>" },
                "requestId": "<some_unique_value>" }');

}

This specification purposely does not define the token structure and the methods to secure tokens. obtain token(s). Providers of the server implementation may choose select their own preferred formats token format and security methods. method for verifying the authenticity of token(s) passed to the server. The server may also treat tokens as opaque structures and pass them on to underlying software layers for evaluation.

While this specification does not mandate the token format and structure it SHALL at least contain the following elements to provide meaningful authorization: Element Description Path The signal path (defined here ) the token authorizes. The path may be a branch name or contain wildcards to authorize entire branches. Actions List of actions that the token authorizes for the path. The list contains at least one of the actions getVSS , get , set , subscribe and unsubscribe . Valid From Timestamp in UTC indicating the date and time from which on the token is valid. Valid Until Tmestamp in UTC indicating the date and time until which the token is valid. It is expected that client and server use the same token format. If a client presents a token using a format that is not understood by the server, ther the server rejects the token.

VSS

In order to make dictionary attacks more difficult, authentication will be denied after a number of failed authentication requests. A 401 (Unauthorized) too_many_requests error will be sent by the server in response to any subsequent authentication requests. The number of failed requests and the period of time during which attempts will be denied is to be determined by the implementation.

Metadata Request

The client MAY use the 'getVSS' 'getMetadata' action to request metadata describing the potentially available signal schema, for example the VSS tree. It does this by sending a 'vssRequest' 'metadataRequest' message to the server. If the server is able to return the VSS metadata, then this is returned using a 'vssSuccessResponse' 'metadataSuccessResponse' message. If an error occurs, the server returns a 'vssErrorResponse' 'metadataErrorResponse' message to the client.

The client is able to request VSS metadata from any point in the VSS signal tree, such that only the metadata for the signals within the given branch of the tree schema's hierachy is returned. For example, only metadata for the chassis branch of the VSS tree is returned when the chassis path is specified. If the path is not set, the response contains the metadata for the entire VSS signal tree.

If more than one 'getVSS' 'getMetadata' call is made with the same 'vssRequest' 'metadataRequest' message content but at different times, the metadata in the 'vssSuccessResponse' 'metadataSuccessResponse' SHALL be the same provided the access-control state of the WebSocket channel has not changed.

{ };

The Vehicle Signal Server (VSS) specification allows branches to be defined as either public or private. The VIS server will satisfy a request for metadata in a public branch regardless of the access control permissions associated with the client making the request. This means that a user could see that a particular signal in a public branch is available but they may not be currently authorised to Get, Set, or Subscribe to that signal. If a branch is defined to be 'private', only suitably authorised clients will be able to retrieve metadata for that branch. This is to enable vehicle manufacturers to apply access controls to metadata for commercially sensitive signals and data.

If a signal is requested to which the client has no access then the server will reject the request as detailed by the Get, Set, and Subscribe sections of this specification. The server shall only return metadata for the branches and nodes which are classified as "Private" branch unless the client has appropriate access permissions. Other data models may also operate similar mechanisms.

Metadata Request Properties

The properties and schema for a metadataRequest is:

Object Name Attribute Type Required
{ }; metadataRequest { };
action Action Yes
path string Yes
requestId string Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Metadata Request",    "description": "Request metadata describing the potentially available signals",    "type": "object",    "required": ["action", "path", "requestId"],    "properties": {        "action": {            "enum": [ "getMetadata" ],            "description": "The identifier for the getMetadata request"
        },
        "path": {            "$ref": "#/definitions/path"
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        }
    }
}

The properties and schema for a metadataSuccessResponse is:

Object Name Attribute Type Required
metadataSuccessResponse
action Action Yes
requestId string Yes
metadata object Yes
timestamp integer Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Metadata Success Response",    "description": "The response sent from the server upon a successful getMetadata request",    "type": "object",    "required": ["action", "requestId", "metadata", "timestamp"],    "properties": {        "action": {            "enum": [ "getMetadata" ],            "description": "The identifier for the getMetadata request"
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        },
        "metadata": {            "$ref": "#/definitions/metadata"
        },
        "timestamp": {            "$ref": "#/definitions/timestamp"
        }
    }
}

The properties and schema for a metadataErrorResponse is:

Object Name Attribute Type Required
metadataErrorResponse
action Action Yes
requestId string Yes
error Error Yes
timestamp integer Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Metadata Error Response",    "description": "The response sent from the server upon an unsuccessful getMetadata request",    "type": "object",    "required": ["action", "requestId", "error", "timestamp"],    "properties": {        "action": {            "enum": [ "getMetadata" ],            "description": "The identifier for the getMetadata request"
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        },
        "error": {            "$ref": "#/definitions/error"
        },
        "timestamp": {            "$ref": "#/definitions/timestamp"
        }
    }
}

Examples

The following data flow example shows a request for the signal structure within the Signal.Body Signal.Drivetrain.InternalCombustionEngine.RPM branch containing signals related to the vehicle body. RPM signal, where the metadata is defined using a VSS tree. A leaf node has been chosen in this example for brevity, however entire VSS branches and other schemas can also be requested using the getMetadata interface.

  client -> {
    ,
    ,

    "action": "getMetadata",
    "path": "Signal.Drivetrain.InternalCombustionEngine.RPM",
    "requestId": "3874"
  }
  receive <- {
    ,
    ,
    : { },

    "action": "getMetadata",
    "requestId": "3874",
    "metadata": { "Signal": {
        "description": "All signals that can dynamically be updated by the vehicle",
        "type": "branch",
        "children": {
          "Drivetrain": {
            "description": "Drivetrain data for internal combustion engines, transmissions, electric motors, etc.",
            "type": "branch",
            "children": {
              "InternalCombustionEngine": {
                "description": "Engine-specific data, stopping at the bell housing.",
                "type": "branch",
                "children": {
                  "RPM": {
                    "description": "Engine speed measured as rotations per minute.",
                    "min": 0,
                    "max": 20000,
                    "type": "UInt16",
                    "id": 54,
                    "unit": "rpm"
                  }
                }
              }
            }
          }
        }
      }
    },
    "timestamp": 1496087968995
  }
  

The following data flow example shows a request for the VSS structure within the Attribute.Body branch of the VSS. The example assumes the VSS contains two leaf nodes within the Attribute.Body branch.


  client -> {
    "action": "getMetadata",    "path": "Attribute.Body",    "requestId": "3875"
  }
  receive <- {
    "action": "getMetadata",    "requestId": "3875",    "metadata": { "Attribute": {        "description": "Attribute signals that do not change during the power cycle of a vehicle.",        "type": "branch",        "children": {          "Body": {            "description": "All body components",            "type": "branch",            "children": {              "BodyType": {                "description": "Body type code as defined by ISO 3779",                "type": "string"
              },
              "RefuelPosition": {                "description": "Location of the fuel cap or charge port",                "type": "string",                "enum": ["front_left", "front_right", "middle_left", "middle_right", "rear_left", "rear_right"]
              }
            }
          }
        }
      }
    },
    "timestamp": 1489985044000
  }
  

Get

The client MAY send a 'getRequest' message to the server to get the value of one or more vehicle signals and data attributes. 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 authorised authorized to retrieve one or more of the signals, then the server SHALL return a 'getErrorResponse'. The structure of these message objects is defined below:

{ };

Get Request Properties

The properties and schema for a getRequest is:

Object Name Attribute Type Required
{ }; getRequest { };
action Action Yes
path string Yes
requestId string Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Get Request",    "description": "Get the value of one or more vehicle signals and data attributes",    "type": "object",    "required": ["action", "path", "requestId"],    "properties": {        "action": {            "enum": [ "get" ],            "description": "The identifier for the get request",
        },
        "path": {            "$ref": "#/definitions/path"
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        }
    }
}

The properties and schema for a getSuccessResponse is:

Object Name Attribute Type Required
getSuccessResponse
action Action Yes
requestId string Yes
value object Yes
timestamp integer Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Get Success Response",    "description": "The response sent from the server upon a successful get request",    "type": "object",    "required": ["action", "requestId", "value", "timestamp"],    "properties": {        "action": {            "enum": [ "get" ],            "description": "The identifier for the get request",
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        },
        "value": {            "$ref": "#/definitions/value"
        },
        "timestamp": {            "$ref": "#/definitions/timestamp"
        }
    }
}

The properties and schema for a getErrorResponse is:

Object Name Attribute Type Required
getErrorResponse
action Action Yes
requestId string Yes
error Error Yes
timestamp integer Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Get Error Response",    "description": "The response sent from the server upon an unsuccessful get request",    "type": "object",    "required": ["action", "requestId", "error", "timestamp"],    "properties": {        "action": {            "enum": [ "get" ],            "description": "The identifier for the get request",
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        },
        "error": {            "$ref": "#/definitions/error"
        },
        "timestamp": {            "$ref": "#/definitions/timestamp"
        }
    }
}

Examples

It is important to note that all examples involving paths are illustrative. Valid path values and the signals and data attributes that correspond to a particular path are defined in the Vehicle Signal Specification.

The example below shows the JSON structure for a 'getRequest' message sent by the client to obtain the engine RPM value and a 'getSuccessResponse' returned by the server.

client -> { , }
       client -> {
                "action": "get",                "path": "Signal.Drivetrain.InternalCombustionEngine.RPM",                "requestId": "8756"
        }

  receive <- {
    ,
    ,
    ,
    
  }
  

        receive <- {
                "action": "get",                "requestId": "8756",                "value": 2372,                "timestamp": 1489985044000
        }
        

In the case where the server returns a value that is a complex type , i.e. a value that is not a single basic JavaScript type (e.g. string, number, boolean), String, Number, Boolean), the value SHALL be returned as a set of name/value pairs in a JSON object structure. The format MUST be as defined by the version of the Vehicle Signal Specification. Specification that is associated with the WebSocket sub-protocol value specified when the WebSocket is created.

The following shows an example of a 'getRequest' that results in the server returning a 'getSuccessResponse' with a value that is a complex type:

client -> { , }
       client -> {
                "action": "get",                "path": "Signal.Body.Trunk",                "requestId": "9078"
        }

  receive <- {
    ,
    ,
    ,
       },
    
  }
  

        receive <- {
                "action": "get",                "requestId": "9078",                "value": { "Signal.Body.Trunk.IsLocked": false,                        "Signal.Body.Trunk.IsOpen": true },                "timestamp": 1489985044000
        }
        

One or more wildcards (denoted by asterisk '*') MAY be included at any level in the path to specify that all nodes at that level are to be included.

In the example below, the path in the 'getRequest' includes a wildcard at the levels above the leaf (signal) node, in order to request just the 'IsLocked' state for all doors.

client -> { , }
       client -> {
                "action": "get",                "path": "Signal.Cabin.Door.*.IsLocked",                "requestId": "4523"
        }

  receive <- {
    ,
    ,
     },
               { },
             { },
             { } ],
    
  }
  

        receive <- {
                "action": "get",                "requestId": "4523",                "value": [ {"Signal.Cabin.Door.Row1.Right.IsLocked" : true },
                           {"Signal.Cabin.Door.Row1.Left.IsLocked" : true },
                               {"Signal.Cabin.Door.Row2.Right.IsLocked" : false },
                               {"Signal.Cabin.Door.Row2.Left.IsLocked" : true } ],
                "timestamp": 1489985044000
        }
        

In this example, a complex type with a nested array is returned in response to the Path: "Signal.Cabin.Door.*" which denotes: 'Return all signals and data attributes for all doors'. For simplicity, the example assumes that the VSS definition for each door only has two attributes 'IsLocked' and 'Window.Position'.

client -> { , }
       client -> {
                "action": "get",                "path": "Signal.Cabin.Door.*",                "requestId": "6745"
        }

  receive <- {
    ,
    ,
    },
               {},
               { },
               { } ],
    
  }
  

        receive <- {
                "action": "get",                "requestId": "6745",                "value": [ {"Signal.Cabin.Door.Row1.Right.IsLocked" : true, "Signal.Cabin.Door.Row1.Right.Window.Position": 50},
                           {"Signal.Cabin.Door.Row1.Left.IsLocked" : true, "Signal.Cabin.Door.Row1.Left.Window.Position": 23},
                           {"Signal.Cabin.Door.Row2.Right.IsLocked" : false, "Signal.Cabin.Door.Row2.Right.Window.Position": 100 },
                           {"Signal.Cabin.Door.Row2.Left.IsLocked": true, "Signal.Cabin.Door.Row2.Left.Window.Position": 0 } ],
                "timestamp": 1489985044000
        }
        

The following shows a request for non-existent data

client -> { , }
       client -> {
                "action": "get",                "path": "Body.Flux.Capacitor",                "requestId": "1245"
        }

  receive <- {
    ,
    ,
    ,
      ,
       },
    
  }
  

        receive <- {
                "action": "get",                "requestId": "1245",                "error": { "number":404,                        "reason": "invalid_path",                        "message": "The specified data path does not exist." },                "timestamp": 1489985044000
        }
        

Set

The client may request that the server sets the value of a signal one or more signals e.g. to lock a door 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 authorised authorized to set the requested value, or the value is read-only, the server SHALL return a 'setErrorResponse' message.

{ };

The properties and schema for a setRequest is:

Object Name Attribute Type Required
{ }; setRequest { };
action Action Yes
path string Yes
value any Yes
requestId string Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Set Request",    "description": "Enables the client to set one or more values once.",    "type": "object",    "required": ["action", "path", "value", "requestId"],    "properties": {        "action": {            "enum": [ "set" ],            "description": "The identifier for the set request",
        },
        "path": {            "$ref": "#/definitions/path"
        },
        "value": {            "$ref": "#/definitions/value"
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        }
    }
}

The properties and schema for a setSuccessResponse is:

Object Name Attribute Type Required
setSuccessResponse
action Action Yes
requestId string Yes
timestamp integer Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Set Success Response",    "description": "The response sent from the server upon a successful set request",    "type": "object",    "required": ["action", "requestId", "timestamp"],    "properties": {        "action": {            "enum": [ "set" ],            "description": "The identifier for the set request",
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        },
        "timestamp": {            "$ref": "#/definitions/timestamp"
        }
    }
}

The properties and schema for a setErrorResponse is:

Object Name Attribute Type Required
setErrorResponse
action Action Yes
requestId string Yes
error Error Yes
timestamp integer Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Set Error Response",    "description": "The response sent from the server upon an unsuccessful set request",    "type": "object",    "required": ["action", "requestId", "error", "timestamp"],    "properties": {        "action": {            "enum": [ "set" ],            "description": "The identifier for the set request",
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        },
        "error": {            "$ref": "#/definitions/error"
        },
        "timestamp": {            "$ref": "#/definitions/timestamp"
        }
    }
}

Examples

Successfully set a signal.

client -> { , , }, { }, { }, { } ] }
    client -> {
      "action": "set",      "path": "Signal.Cabin.Door.*.IsLocked",      "value": [ {"Row1.Right.IsLocked": true },
                 {"Row1.Left.IsLocked": true },
                 {"Row2.Right.IsLocked": true },
                 {"Row2.Left.IsLocked": true } ],
      "requestId": "5689"
    }
  receive <- {
    ,
    ,
     },
                { },
            { },
            { } ] },
    
  }
  

    receive <- {
        "action": "set",        "requestId": "5689",        "timestamp": 1489985044000
    }
        

Unsuccessful set. The value cannot be set.

client -> { , , }
    client -> {
        "action": "set",        "path": "Signal.Drivetrain.InternalCombustionEngine.RPM",        "value": 2000,        "requestId": "8912"
    }

  receive <- {
    ,
    ,
    ,
      ,
      },
    

    receive <- {
        "action": "set",        "requestId": "8912",        "error": { "number": 401,        "reason": "read_only",        "message": "The desired signal cannot be set since it is a read only signal"},        "timestamp": 1489985044000
    }
  

        

Unsuccessful set. The value does not exist in the specified path.

client -> { , , } } receive <- { , , , , "The server is unable to fulfil the client request because the request is malformed."},
    client -> {
    "action": "set",
    "path": "Signal.Drivetrain.InternalCombustionEngine.RPM",
    "value": { "locked" : true }
    "requestId": "2311"

    }
  

    receive <- {
        "action": "set",
        "requestId": "2311",
        "error": { "number": 400,
        "reason": "bad_request" ,
        "message": "The server is unable to fulfil the client
                    request because the request is malformed."},
        "timestamp": 1489985044000
     }
        

Subscribe

Vehicle data subscriptions provide data to the client whenever the signal changes on the server, unless otherwise specified using Server Side Filtering. The server MAY reduce the number of notifications sent to the client in order to reduce processing demands, particularly when the client has subscribed to continuously varying signals.

When the client makes a request to the server to create a new subscription, a JSON data object is returned. This object contains the attributes that were passed to the server to make the subscription and a 'subscriptionId' integer handle value which is used to uniquely identify the subscription.

{ };

Subscribe Request Properties

The properties and schema for a subscribeRequest is:

Object Name Attribute Type Required
{ }; subscribeRequest { };
{ }; action { }; Action Yes
path string Yes
filters object No
requestId string Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Subscribe Request",    "description": "Allows the client to subscribe to time-varying signal notifications on the server.",    "type": "object",    "required": ["action", "path", "requestId"],    "properties": {        "action": {            "enum": [ "subscribe" ],            "description": "The identifier for the subscription request"
        },
        "path": {            "$ref": "#/definitions/path"
        },
        "filters": {            "$ref": "#/definitions/filters"
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        }
    }
}

The properties and schema for a subscribeSuccessResponse is:

Object Name Attribute Type Required
subscribeSuccessResponse
action Action Yes
requestId string Yes
subscriptionId string Yes
timestamp integer Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Subscribe Success Response",    "description": "The response sent from the server upon a successful subscription request",    "type": "object",    "required": ["action", "requestId", "subscriptionId", "timestamp"],    "properties": {        "action": {            "enum": [ "subscribe" ],            "description": "The identifier for the subscription request",
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        },
        "subscriptionId": {            "$ref": "#/definitions/subscriptionId"
        },                
        "timestamp": {            "$ref": "#/definitions/timestamp"
        }
    }
}

The properties and schema for a subscribeErrorResponse is:

Object Name Attribute Type Required
subscribeErrorResponse
action Action Yes
requestId string Yes
error Error Yes
timestamp integer Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Subscribe Error Response",    "description": "The response sent from the server upon an unsuccessful subscribe request",    "type": "object",    "required": ["action", "requestId", "error", "timestamp"],    "properties": {        "action": {            "enum": [ "subscribe" ],            "description": "The identifier for the subscription request",
        },
        "requestId": {            "$ref": "#/definitions/requestId"
        },
        "error": {            "$ref": "#/definitions/error"
        },
        "timestamp": {            "$ref": "#/definitions/timestamp"
        }
    }
}

The properties and schema for a subscriptionNotification is:

Object Name Attribute Type Required
subscriptionNotification
action Action Yes
subscriptionId string Yes
value any Yes
timestamp integer Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Subscription Notification",    "description": "Notification sent from the server to provide the requested data to the client",    "type": "object",    "required": ["action", "subscriptionId", "value", "timestamp"],    "properties": {        "action": {            "enum": [ "subscription" ],            "description": "The identifier for the subscription notification",
        },
        "subscriptionId": {            "$ref": "#/definitions/subscriptionId"
        },
        "value": {            "$ref": "#/definitions/value"
        },
        "timestamp": {            "$ref": "#/definitions/timestamp"
        }
    }
}

The properties and schema for a subscriptionNotificationError is:

Object Name Attribute Type Required
subscriptionNotificationError
action Action Yes
subscriptionId string Yes
error Error Yes
timestamp integer Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Subscription Notification Error",    "description": "Error message sent by the server when there is an error with an existing subscription",    "type": "object",    "required": ["action", "subscriptionId", "error", "timestamp"],    "properties": {        "action": {            "enum": [ "subscription" ],            "description": "The identifier for the subscription notification",
        },
        "subscriptionId": {            "$ref": "#/definitions/subscriptionId"
        },
        "error": {            "$ref": "#/definitions/error"
        },
        "timestamp": {            "$ref": "#/definitions/timestamp"
        }
    }
}

Examples

For example when a client need wishes to subscribe to continuously receive "Signal.Drivetrain.Transmission.TripMeter" information from the server, it can use the "subscribe" action with the target path property like below. client -> { , , } set as follows:


       client -> {
                "action": "subscribe",                "path": "Signal.Drivetrain.Transmission.TripMeter",                "requestId": "1004"
        }

  receive <- {
    ,
    ,
    ,
    
  }
  

        receive <- {
            "action": "subscribe",            "requestId": "1004",            "subscriptionId": "35472",            "timestamp": 1489985044000
        }
  

When this

This example is for illustrative purposes only, it MAY or MAY NOT be the case that the version of the Vehicle Server Specification implemented by the VIS Server includes the example path 'Signal.Drivetrain.Transmission.TripMeter'.

If the "subscribe" request has been successed, client is successful the server will receive return a notificaton with changing value continuously subscribeSuccessResponse as below JSON structure. receive <- { , , , } The client can use shown in the 'requestId' value to associate example above, and the successful client will then start to receive subscription response with notifications like the original request. one illustrated in the following JSON structure:

      receive <- {
          "action": "subscription",          "subscriptionId": "35472",          "value": 36912,          "timestamp": 1489985044000
      }
  

The 'subscriptionId' value is a unique value, created by the server and which is may be used internally by the server to manage subscriptions on that WebSocket instance.

The subscription id subscriptionId value may also be used by the client to unsubscribe from receiving future notifications, by passing the handle value to the server with the unsubscribe action.

To differentiate subscription response from responses for ‘GET’ requests, subscription responses shall additionally include the subscription id subscriptionId value that identifies the subscription that triggered that notification.

The server ensures that a new unique subscription id subscriptionId value is returned for each successful subscription request on a particular WebSocket connection. However the server does not guarantee that subscription handle values are unique between different WebSocket instances.

Once the subscription is successfully registered with the server, the client receives subscription notifications containing the requested data, at a rate defined either by the server or by the server side filter. If there is an error with an existing subscription a subscriptionNotificationError is received by SHALL be sent to the client. This allows the client to handle the error, such as for example by modifying the filter condition to reduce the requested notification frequency.

If the authentication token expires whilst a subscription frequency if is active, the server will send a subscriptionNotificationError for each subscription that can no longer be fulfilled. The client is unable then responsible for communicating with the relevant Security Authority to satisfy renew the initial demands authentication token.

After the client authentication token has expired, the server MAY continue to send notifications for data that is not subject to access control restrictions. The client will NOT receive notifications for subscriptions that require a valid authentication token until the client sends a renewed authentication token to the server.

If a new authentication token is presented by the client to the server in a timely manner, all existing subscriptions will continue to cause notifications to be sent from the server, provided the security principal(s) have not changed. The time window during which the client MAY re-authenticate and subscriptions continue WILL be implementation dependent. If the server has terminated any subscriptions, it is the responsibility of the client to renew them.

At any time the server MUST only send subscription notifications for data that the client is authorized to access.

The server MAY close the WebSocket connection at any time and in so doing, terminate all subscriptions for the client. The client is then responsible for renewing subscriptions. The client MUST close the WebSocket connection if the server data is no longer required.

An example of a subscription can be found here .

Unsubscribe

To unsubscribe from a subscription, the client SHALL send an 'unsubscribeRequest' message to the server. This is comprised of a JSON structure which contains an action property set to 'unsubscribe' and a string containing the 'subscriptionId'. If the server is able to satisfy the request it returns an 'unsubscribeSuccessResponse'. If an error occurs, for example because an invalid subscriptionId is passed to the server, an 'unsubscribeErrorResponse' is returned.

The client MAY unsubscribe from all of its subscriptions by sending an 'unsubscribeRequest' with the action property set to 'unsubscribeAll'. This does not require a subscriptionId value. 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.

It is not possible to unsubscribe from a subset of signals within a subscription. The client must unsubscribe and set up a new subscription to receive notifications for the desired signals. For example, if there is an active subscription for all lights, using the path Signal.Body.Lights.*, and the client requires information for only Signal.Body.Lights.IsLowBeamOn, the client will have to unsubscribe from the Signal.Body.Lights.* subscription and re-subscribe to Signal.Body.Lights.IsLowBeamOn.

The client should always unsubscribe from receiving notifications when it is no longer using the data. Over a long vehicle journey, this significantly reduces the processing load on the server and allow the server to free memory. It therefore makes it more likely that the server remains will remain responsive to future requests from the client.

Unsubscribe Request Properties

The 'unsubscribe' message structures are defined below: properties and schema for a unsubscribeRequest is:

{ };
Object Name Attribute Type Required
{ }; unsubscribeRequest { };
action Action Yes
subscriptionId string Yes
requestId string Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Unsubscribe Request",    "description": "Allows the client to unsubscribe to time-varying signal notifications on the server.",    "type": "object",    "required": ["action", "subscriptionId", "requestId"],    "properties": {        "action": {            "enum": [ "unsubscribe" ],            "description": "The identifier for the unsubscribe request"
        },
        "subscriptionId": {            "$ref": "#/definitions/subscriptionId"
        }, 
        "requestId": {            "$ref": "#/definitions/requestId"
        }
    }
}

Unsubscribe from

The properties and schema for a single subscription. client -> { , , } unsubscribeSuccessResponse is:

Object Name Attribute Type Required
receive <- { , , , } unsubscribeSuccessResponse
action Action Yes
subscriptionId string Yes
requestId string Yes
timestamp integer Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Unsubscribe Success Response",    "description": "The response sent from the server upon a successful unsubscribe request",    "type": "object",    "required": ["action", "subscriptionId", "requestId", "timestamp"],    "properties": {        "action": {            "enum": [ "unsubscribe" ],            "description": "The identifier for the unsubscribe request"
        },
        "subscriptionId": {            "$ref": "#/definitions/subscriptionId"
        }, 
        "requestId": {            "$ref": "#/definitions/requestId"
        },
        "timestamp": {            "$ref": "#/definitions/timestamp"
        }
    }
}

Unsubscribe

The properties and schema for a unsubscribeErrorResponse is:

Object Name Attribute Type Required
unsubscribeErrorResponse
action Action Yes
subscriptionId string Yes
requestId string Yes
error Error Yes
timestamp integer Yes

{
    "$schema": "http://json-schema.org/draft-04/schema#",    "title": "Unsubscribe Error Response",    "description": "The response sent from the server upon an unsuccessful unsubscribe request",    "type": "object",    "required": ["action", "subscriptionId", "requestId", "error", "timestamp"],    "properties": {        "action": {            "enum": [ "unsubscribe" ],            "description": "The identifier for the subscription request"
        },
        "subscriptionId": {            "$ref": "#/definitions/subscriptionId"
        }, 
        "requestId": {            "$ref": "#/definitions/requestId"
        },
        "error": {            "$ref": "#/definitions/error"
        },
        "timestamp": {            "$ref": "#/definitions/timestamp"
        }
    }
}

Examples

The example below shows the JSON message structure for a 'unsubscribeRequest' and 'unsubscribeSuccessResponse' to unsubscribe from all subscriptions. client -> { , } a single subscription.

       client -> {
                "action": "unsubscribe",                "subscriptionId": "102",                "requestId": "5264"
        }

  receive <- {
    ,
    ,
    ,
    
  }
  

        receive <- {
                "action": "unsubscribe",                "subscriptionId": "102",                "requestId": "5264",                "timestamp": 1489985044000
        }
        

Error The following shows an example of error case - with invalid ID client -> { , , } receive <- { , , , , }, , } susbscriptionId.

       client -> {
                "action": "unsubscribe",                "subscriptionId": "3542",                "requestId": "7846"
        }
        receive <- {
                "action": "unsubscribe",                "subscriptionId": "3542",                "requestId": "7846",                "error": { "number":404,                        "reason": "invalid_subscriptionId",                        "message": "The specified subscription was not found." },                "timestamp": 1489985044000
        }
        

Example 4 5
// send unsubscribe message
vehicle.send();

vehicle.send('{ "action": "unsubscribe", "subscriptionId": "102", "requestId": "5429" }');

// set handler
vehicle.onmesssage(function(event){
  .parse(event.data);
  
  ){
     + msg.subscriptionId);
  
  } )) {
     + msg.error.message)
  }

        var msg = JSON.parse(event.data);
        // success case
        if(msg.hasOwnProperty("requestId") && msg.requestId == "5429"){
                console.log("Successfully unsubscribed for id " + msg.subscriptionId);
        // error case
        } else if (msg.hasOwnProperty("error")) {
                console.log("Unsuccessful unsubscribe. " + msg.error.message)
        }

});

Unsubscribe All

To unsubscribe from all subscriptions, the client SHALL send an 'unsubscribeAllRequest' message to the server. This is comprised of a JSON structure which contains an action property set to 'unsubscribeAll'. This does not require a subscriptionId value. If the request is successful, or there are no active subscriptions to unsubscribe from, the VIS Server will return an 'unsubscribeSuccessResponse'.

Unsubscribe All Request Properties

The properties and schema for a unsubscribeAllRequest is:

Object Name Attribute Type Required
unsubscribeAllRequest
action Action Yes
requestId string Yes

{
  "$schema": "http://json-schema.org/draft-04/schema#",  "title": "unsubscribeAll Request",  "description": "Allows the client to unsubscribe from all notifications on the server.",  "type": "object",  "required": ["action", "requestId"],  "properties": {    "action": {      "enum": [ "unsubscribeAll" ],      "description": "The identifier for the unsubscribeAll request"
    },
    "requestId": {      "$ref": "#/definitions/requestId"
    }
  }
}

The properties and schema for a unsubscribeAllSuccessResponse is:

Object Name Attribute Type Required
unsubscribeAllSuccessResponse
action Action Yes
requestId string Yes
timestamp integer Yes

{
  "$schema": "http://json-schema.org/draft-04/schema#",  "title": "unsubscribeAll Success Response",  "description": "The response sent from the server upon a successful unsubscribeAll request",  "type": "object",  "required": ["action", "requestId", "timestamp"],  "properties": {    "action": {      "enum": [ "unsubscribeAll" ],      "description": "The identifier for the unsubscribeAll request"
    },
    "requestId": {      "$ref": "#/definitions/requestId"
    },
    "timestamp": {      "$ref": "#/definitions/timestamp"
    }
  }
}

The properties and schema for a unsubscribeAllErrorResponse is:

Object Name Attribute Type Required
unsubscribeAllErrorResponse
action Action Yes
requestId string Yes
error Error Yes
timestamp integer Yes

{
  "$schema": "http://json-schema.org/draft-04/schema#",  "title": "UnsubscribeAll Error Response",  "description": "The response sent from the server upon an unsuccessful unsubscribeAll request",  "type": "object",  "required": ["action", "requestId", "error", "timestamp"],  "properties": {    "action": {    "enum": [ "unsubscribeAll" ],    "description": "The identifier for the unsubscribeAll request"
    },
    "requestId": {      "$ref": "#/definitions/requestId"
    },
    "error": {      "$ref": "#/definitions/error"
    },
    "timestamp": {      "$ref": "#/definitions/timestamp"
    }
  }
}

Examples

The example below shows an example of a 'unsubscribeAllRequest' and 'unsubscribeAllSuccessResponse' for unsubscribeAll action, in order to unsubscribe from all subscriptions.

client -> {
    "action": "unsubscribeAll",    "requestId": "3468"
}
receive <- {
    "action": "unsubscribeAll",    "requestId": "3468",    "timestamp": 1489985044000
}

9. Server Side Filtering

' Filters ' may be specified to enable Server side filtering to be used in order to throttle the demands of subscriptions on the server. This may enable the reduction of traffic if the developer has received a 429 '429 - Too Many Requests Requests' error message. This can be implementation dependent

Server side filters are extensible, allowing for additional filtering mechanisms to be specified. Support is currently included for a number specific range of potential filtering mechanisms, such as ranges, values, time intervals and minimum changes. This can be implemented using the "filters" option. option in the subscribeRequest interface.

Filters can only be applied for data which is represented by a primitive type, such as leaf nodes in the VSS tree, not entire branches. For example, a filter cannot be set on engine.*, Signal.Drivetrain.InternalCombustionEngine.*, however it can be set on engine.rpm. Signal.Drivetrain.InternalCombustionEngine.RPM.

The default behaviour for a subscription currently defaults is to sending values request that the server sends a notification to the client only onchange, however 'onchange'. To modify this may cause unnecessary processing demands on behaviour the vehicle server. A filter object client can use filtering options. The following filter options SHALL be included in the subscription request: { , } Potential tags could include: supported:

If The client can use filters to request that the filter server sends notifications based on various criteria, but it is not set, or important to note that this is unsupported by the server, just a request and the notification frequency is will ultimately be determined by the server.

{ ,

JSON Schema


{
  "filters": {      "$ref": "#/definitions/filters"
  }
}

Examples

The following structures are examples of subscribeRequest objects which are requesting server side filters

 //client receives data every 100ms
        { "action": "subscribe", "path": "<any_path>",

                "filters": { "interval": 100 },
                "requestId": "<some_unique_value>" }
  
  { ,

        //client receives data when the value is between 100 and 200 (inclusive)
        { "action": "subscribe", "path": "<any_path>",

                "filters": { "range": { "above": 100, "below": 200 } },
                "requestId": "<some_unique_value>" }
  
  { ,

        //client receives data when the value is below 100 (inclusive)
        { "action": "subscribe", "path": "<any_path>",

                "filters": { "range": { "below": 100 } },
                "requestId": "<some_unique_value>" }
  
  { ,
                 },
                 }
  
  { ,

        //client receives data when the value changes by 100 units
        { "action": "subscribe", "path": "<any_path>",

                "filters": { "minChange": 100 },
                "requestId": "<some_unique_value>" }
  
  
  { ,

        //client receives data when the value is above 200 (inclusive)
        //and the value changes by 20 units
        { "action": "subscribe", "path": "<any_path>",

                "filters": { "range": { "below": 200 }, "minChange": 20},
                "requestId": "<some_unique_value>" }
      

When the range filter is used a final message is sent when the value returned is outside of the specified range. For example, if the range states { "below": 100 }, a final value may be received at 101 to indicate that the value is now out of range. The client should not specify a minimum change amount that is smaller than it needs - in order to prevent adding unnecessary load on the server. The server shall return a '429 - Too Many Request' error response if it is unable to fulfil the request made by the client.

The section that follows defines the error responses that shall be supported by the server.

10. 9.1 Web Socket WebSocket Closure

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:

Example 5 6
// Open the WebSocket
var vehicle  = new WebSocket("wss://localhost:4343", "wvss1.0");
// WebSocket is used to GET, SET, SUBSCRIBE and UNSUBSCRIBE// Close the WebSocket
vehicle.close();

The WebSocket server VIS 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 section that follows defines the error responses that shall be supported by the server.

11. 9.2 Errors

If there is an error with any of the client’s requests, the server responds with an error number, reason and message.

{ };

The properties and schema for an Error object is:

Object Name Attribute Type Required
Error
number integer Yes
reason string Yes
message string Yes

{
  "error": {      "$ref": "#/definitions/error"
  }
}

Examples

For some error codes, for example '401 (Unauthorised)' (Unauthorized)' there can be more than one cause. The error number that is returned is the HTTP Status Code Number e.g. 401. An error reason is also returned, this contains a pre-defined string value that can be used to distinguish between errors that have the same code (e.g. '401 Unauthorized)' but a difference cause. The error message is used to provide message text describing the cause in more detail.

client -> { , }, , } receive on error <- { , , }, , }
      client -> { 
        "action": "subscribe",        "filters": { "<filter_expression>" },        "path": "<any_metadata_definition>",        "requestId": "<some_unique_value>" 
      }
      receive on error <- {
          "action": "subscribe",          "requestId": "<some_unique_value>",          "error":{             "number": "<error_num>",            "reason": "<error_reason>",            "message": "<error_message>" 
          },
          "timestamp": "1489985044000" 
        }
        

The server implementation supports at least the error numbers and reasons listed in the table below.

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 (Unauthorised) (Unauthorized) user_token_expired User token has expired.
401 (Unauthorised) (Unauthorized) user_token_invalid User token is invalid.
401 (Unauthorised) (Unauthorized) user_token_missing User token is missing.
401 (Unauthorised) (Unauthorized) device_token_expired Device token has expired.
401 (Unauthorised) (Unauthorized) device_token_invalid Device token is invalid.
401 (Unauthorised) (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 authorised 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 server may optionally return additional error codes. It is expected that if this is the case, they are defined in the Server Documentation. Wherever possible the Server returns a standard HTTP error code where one has been defined for the error condition. See for example RFC7231 , RFC7235 , and RFC6585 .

A. References

A.1 Normative references

[RFC2119]
S. Bradner. IETF. Key words for use in RFCs to Indicate Requirement Levels . S. Bradner. IETF. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[VSS]
Vehicle Signal Specification . GENIVI Alliance. March 2017. 1.0. URL: https://github.com/GENIVI/vehicle_signal_specification