Skip to content

Commit

Permalink
Feature: Document AppManifest version 3 design (#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
doosuu authored Aug 15, 2023
1 parent a1f2202 commit f370892
Show file tree
Hide file tree
Showing 18 changed files with 1,160 additions and 111 deletions.
243 changes: 136 additions & 107 deletions content/en/docs/concepts/development_model/vehicle_app_manifest/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,142 +7,171 @@ description: >
---

## Versions

* v1
* v2
* **v3 (current)**

## Introduction

The _AppManifest_ defines the name and the requirements of a _Vehicle App_. The requirements are specified on interface level. The manifest defines the required service interfaces (e.g. gRPC functions) and the used vehicle model and accessed data points, but it does not define certain providers of those interfaces.
This concept provides flexibility by separating the requirements of a _Vehicle App_ from the definition of a concrete _Runtime_ and _Middleware_ configuration.
The _AppManifest_ defines the properties of your _Vehicle App_ and its _functional interfaces_ (**FIs**).

**FIs** may be:

* required service interfaces (e.g. a required gRPC service interface)
* the used vehicle model and accessed data points.
* an arbitrary abstract interface description used by 3rd parties

In addition to _required_ **FIs**, _provided_ **FIs** can (and need) to be specified as well.

These defined interfaces are then used by the Velocitas toolchain to:

* generate service stubs for either a client implementation (required IF) or a server implementation (provided IF) (i.e. for gRPC)
* generate a source code equivalent of the defined vehicle model

## Overview

The image below depicts the interaction between _App Manifest_ and _DevEnv Configuration_ at -development time- The responsibilities are clearly separated; the _App Manifest_ describes the application and its interfaces whereas _DevEnv Configuration_ (or `.velocitas.json`) defines the configuration of the development environment and all the packages used by the Velocitas toolchain.

![Overview](./new_app_manifest_overview.drawio.svg)

## Context

The AppManifest is the only source of truth in our _Vehicle App_ templates for:
To fully understand the _AppManifest_, let's have a look at **who** interacts with it:

- Local development environments and configs
- deployment specs generation
- Velocitas CI/CD workflow
- OCI Image creation
![Manifest Context](./manifest_context.drawio.png)

## Purpose

- The AppManifest contains necessary information about the runtime requirements (VehicleModel, interfaces) of the app
- The AppManifest contains all required (or optional) data points that are used in the _Vehicle App_ with the necessary access rights (read, write)
- The AppManifest is service provider/implementation agnostic, while the service configurations are part of a corresponding [Velocitas Lifecycle Management](/docs/concepts/lifecycle_management) runtime package
* Define the requirements of a _Vehicle App_ in an **abstract way** to avoid dependencies on concrete _Runtime_ and _Middleware_ configurations.
* Description of your applications **functional interfaces**(VehicleModel, services, APIs, ...)
* Enable **loose coupling** of functional interface descriptions and the Velocitas toolchain. Some parts of the toolchain are responsible for reading the file and acting upon it, depending on the type of functional interface
* Providing an **extendable** syntax to enable custom functional interface types which may not provided by the Velocitas toolchain itself, but by a third party
* Providing a **single source of truth** for generation of deployment specifications (i.e. Helm-Charts, Kanto spec, etc...)

## Structure
## Example

```json
// AppManifest.json
{
"name":"SampleApp",
"vehicleModel":{
"src":"https://github.com/COVESA/vehicle_signal_specification/releases/download/v3.0/vss_rel_3.0.json",
"datapoints":[
{
"path":"Vehicle.Speed",
"required":"true",
"access":"read"
}
]
},
"runtime":[
"grpc://sdv.databroker.v1.Broker/GetDatapoints",
"grpc://sdv.databroker.v1.Broker/Subscribe",
"grpc://sdv.databroker.v1.Broker/SetDatapoints",
"mqtt"
]
"manifestVersion": "v3",
"name": "SampleApp",
"interfaces": [
{
"type": "vehicle-signal-interface",
"config": {
"src": "https://github.com/COVESA/vehicle_signal_specification/releases/download/v3.0/vss_rel_3.0.json",
"datapoints": {
"required": [
{
"path": "Vehicle.Speed",
"optional": "true",
"access": "read",
}
],
"provided": [
{
"path": "Vehicle.Cabin.Seat.Row1.Pos1.Position",
}
]
}
}
},
{
"type": "grpc-interface",
"config": {
"src": "https://raw.githubusercontent.com/eclipse/kuksa.val.services/main/seat_service/proto/sdv/edge/comfort/seats/v1/seats.proto",
"required": {
"methods": [ "Move", "MoveComponent" ]
},
}
},
{
"type": "pubsub",
"config": {
"reads": [ "sampleapp/getSpeed" ],
"writes": [ "sampleapp/currentSpeed", "sampleapp/getSpeed/response" ]
}
}
}
```

## Vehicle Model Description
The _VehicleApp_ above has an:

The [_Vehicle Model_](/docs/concepts/development_model/#vehicle-models) of the _Vehicle App_ is described with the source and required (or optional) data points.
More information: [Vehicle Model Creation](/docs/tutorials/vehicle_model_creation/)
* interface towards our generated Vehicle Signal Interface based on the [COVESA Vehicle Signal Specification](https://github.com/COVESA/vehicle_signal_specification). In particular, it requires read access to the vehicle signal `Vehicle.Speed` since the signal is marked as _optional_ the application will work, even if the signal is not present in the system. Additionally, the application acts as a provider for the signal `Vehicle.Cabin.Seat.Row1.Pos1.Position` meaning that it will take responsibility of reading/writing data directly to vehicle networks for the respective signal.

The source ("src") identifies the used _Vehicle Model_ description and the data points section defines which signals (i.e. data points) of that model need to be available for the _Vehicle App_ to run:
* interface towards gRPC based on the `seats.proto` file. Since the `direction` is `required` a service client for the `seats` service will be generated who interacts with the Velocitas middleware.

- The `path` references the definition (type, data type, unit, and other metadata) of a data point in the specified model
- The `required` flag tells if that data point is mandatory for the app to run or just optional
- `access` defines the required access right of the app to that data point (see below)
* interface towards the `pubsub` middleware and is reading to the topic `sampleapp/getSpeed` and writing the topics `sampleapp/currentSpeed`, `sampleapp/getSpeed/response`.

Further information can be found here: [How to Reference a Model Specification](/docs/tutorials/vehicle_model_creation/automated_model_lifecycle/#how-to-reference-a-model-specification)
</br>
The example has no provided interfaces.

### Data Point Access Rights
## Structure

Describes all external properties and interfaces of a Vehicle Application.

### Properties

{{<table "table table-bordered">}}
| Access Right | Description | Vehicle Databroker Interface |
|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------|
| read | app needs to read the value of the data point from the provider (e.g. get value from databroker). | GetDatapoints/Subscribe |
| write | app needs to get and set the value of the data point (e.g. set, set_many values via the databroker or services). WRITE access implicitly has READ access. | SetDatapoints |
| Property | Type | Required | Description |
|-------------------|-------------------------|----------|----------------------------------------------------------|
| `manifestVersion` | string | **Yes** | The version of the App Manifest. |
| `name` | string | **Yes** | The name of the Vehicle Application. |
| `interfaces` | [object](#interfaces)[] | No | Array of all provided or required functional interfaces. |
{{</table>}}

## AppManifest Examples
### interfaces

{{< tabpane lang="json">}}
{{< tab "Runtime interface via databroker" >}}
#### Properties

// Here we have a dependency to the databroker, the App doesn't have any direct
// connection to the SeatService because the databroker forwards the set requests from
// the app via SetDatapoints to the corresponding SeatService
{{<table "table table-bordered">}}
| Property | Type | Required | Description |
|----------|-------------------|----------|-----------------------------------------------------------------------------------------|
| `type` | string | **Yes** | The type of the functional interface. |
| `config` | [object](#config) | No | The configuration of the functional interface type. Content may vary between all types. |

{
"name": "SeatAdjuster",
"vehicleModel": {
"src": "./app/vehiclemodel/used_vss.json",
"datapoints": [
{
"path": "Vehicle.Cabin.Seat.Row1.Pos1.Position",
"required": "true",
"access": "write"
},
{
"path": "Vehicle.Speed",
"required": "true",
"access": "read"
}
],
},
"runtime": [
"grpc://sdv.databroker.v1.Broker/GetDatapoints",
"grpc://sdv.databroker.v1.Broker/Subscribe",
"grpc://sdv.databroker.v1.Broker/SetDatapoints",
"mqtt"
]
}
{{< /tab >}}
{{< tab "Runtime interface via specific service" >}}
{{</table>}}

// Here the app establishes a direct gRPC connection to the
// Vehicle SeatService and adjusts the seat position via
// the MoveComponent Interface
#### config

{
"name": "SeatAdjuster",
"vehicleModel": {
"src": "./app/vehiclemodel/used_vss.json",
"datapoints": [
{
"path": "Vehicle.Cabin.Seat.Row1.Pos1.Position",
"required": "true",
"access": "read"
},
{
"path": "Vehicle.Speed",
"required": "true",
"access": "read"
}
],
},
"runtime": [
"grpc://sdv.databroker.v1.Broker/GetDatapoints",
"grpc://sdv.databroker.v1.Broker/Subscribe",
"grpc://sdv.edge.comfort.seats.v1.Seats/MoveComponent"
"mqtt"
]
}
{{< /tab >}}
{{< /tabpane >}}
The configuration of the functional interface type. Content may vary between all types.

Refer to the [JSON Schema](https://json-schema.org/) of the current _AppManifest_ [here](./manifest.v3.schema.json).

### Visualization

```mermaid

graph TD
manifest(manifest.json)
manifest --> manifestVersion[manifestVersion]
manifest --> name[name]
manifest -.-> interfaces[interfaces]

interfaces -- "0..n" --> interfaces.item(object)
interfaces.item --> interfaces.item.type[type]
interfaces.item -.-> interfaces.item.config[config]

```

### Functional interface types supported by Velocitas

Here is a list of functional interface types directly supported by the Velocitas toolchain and which Velocitas CLI packages are exposing the support:

* [Vehicle Model](./interfaces/vehicle_model/)
* [gRPC interface](./interfaces/grpc_interface/)
* [Publish and subscribe](./interfaces/pubsub/)

Support for additional interface types may be added by providing a 3rd party [CLI package](/docs/concepts/lifecycle_management/packages/).

## Planned, but not yet available features

Some FIs are dependent on used classes, methods or literals in your _Vehicle App_'s source code. For example the `vehicle-model` FI requires you to list required or provided datapoints. At the moment, these attributes need to be filled **manually**. There are ideas to auto-generate these attributes by analyzing the source code, but nothing is planned for that, yet.

## Further information

- Tutorial: [Quickstart](/docs/tutorials/quickstart.md)
- Tutorial: [Vehicle Model Creation](/docs/tutorials/vehicle_model_creation)
- Tutorial: [_Vehicle App_ Development](/docs/tutorials/vehicle_app_development)
- Concept: [Lifecycle Management](/docs/concepts/lifecycle_management)
* Tutorial: [Quickstart](/docs/tutorials/quickstart.md)
* Tutorial: [Vehicle Model Creation](/docs/tutorials/vehicle_model_creation)
* Tutorial: [_Vehicle App_ Development](/docs/tutorials/vehicle_app_development)
* Concept: [Lifecycle Management](/docs/concepts/lifecycle_management)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: "Interfaces"
date: 2023-05-31T13:33:25+05:30
weight: 10
description: >
Learn more about logical interfaces.
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
title: "gRPC Service Interface"
date: 2023-08-09T00:00:00+01:00
weight: 20
description: >
The functional interface for supporting remote procedure calls via gRPC.
---

{{<table "table table-bordered">}}
| Providing CLI package | Interface type-key |
|-----------------------------|-----------------------|
| `devenv-devcontainer-setup` | `grpc-interface` |
{{</table>}}

## Description

This interface type introduces a dependency to a gRPC service. It is used to generate either client stubs (in case your application requires the interface) or server stubs (in case your application provides the interface). The result of the generation is a language specific and package manager specific source code package, integrated with the Velocitas SDK core.

If a _Vehicle App_ requires a `grpc-interface` - a client stub embedded into the Velocitas framework will be generated and added as a build-time dependency of your application. It enables you to access your service from your _Vehicle App_ without any additional effort.

If a _Vehicle App_ provides a `grpc-interface` - a server stub embedded into the Velocitas framework will be generated and added as a build-time dependency of your application. It enables you to quickly add the business logic of your application.

## Configuration structure

{{<table "table table-bordered">}}
| Attribute | Example value | Description |
|-|-|-|
| `src` | `"https://raw.githubusercontent.com/eclipse/kuksa.val.services/v0.2.0/seat_service/proto/sdv/edge/comfort/seats/v1/seats.proto"` | URI of the used protobuf specification of the service. URI may point to a local file or to a file provided by a server. It is generally recommended that a **stable** proto file is used. I.e. one that is already released under a proper tag rather than an in-development proto file. |
| `required.methods` | | Array of service's methods that are accessed by the application. In addition to access control the methods attribute may be used to determine backward or forward compatibility i.e. if semantics of a service's interface did not change but methods were added or removed in a future version. |
| `required.methods.[].name` | `"Move"`, `"MoveComponent"` | Name of the method that the application would like to access |
| `provided` | `{}` | Reserved object indicating that the interface is provided. Might be filled with further configuration values.
{{</table>}}

## Example

```json
{
"type": "grpc-interface",
"config": {
"src": "https://raw.githubusercontent.com/eclipse/kuksa.val.services/v0.2.0/seat_service/proto/sdv/edge/comfort/seats/v1/seats.proto",
"required": {
"methods": [
"Move", "MoveComponent"
]
}
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: "Publish Subscribe"
date: 2023-08-09T00:00:00+01:00
weight: 20
description: >
The functional interface for supporting communication via publish and subscribe.
---

{{<table "table table-bordered">}}
| Providing CLI package | Interface type-key |
|-----------------------------|-----------------------|
| `devenv-runtimes` | `pubsub` |
{{</table>}}

## Description

This interface type introduces a dependency to a publish and subscribe middleware. While this may change in the future due to new middlewares being adopted, at the moment this will always indicate a dependency to MQTT.

If a _Vehicle App_ requires `pubsub` - this will influence the generated deployment specs to include a publish and subscribe broker (i.e. an MQTT broker).

If a _Vehicle App_ provides `pubsub` - this will influence the generated deployment specs to include a publish and subscribe broker (i.e. an MQTT broker).

## Configuration structure

{{<table "table table-bordered">}}
| Attribute | Example value | Description |
|-|-|-|
| `reads` | `[ "sampleapp/getSpeed" ]` | Array of topics which are read by the application. |
| `writes` | `[ "sampleapp/currentSpeed", "sampleapp/getSpeed/response" ]` | Array of topics which are written by the application. |
{{</table>}}

## Example

```json
{
"type": "pubsub",
"config": {
"reads": [ "sampleapp/getSpeed" ],
"writes": [ "sampleapp/currentSpeed", "sampleapp/getSpeed/response" ]
}
}
```
Loading

0 comments on commit f370892

Please sign in to comment.