diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000..7c00777
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,50 @@
+// For format details, see https://aka.ms/devcontainer.json. For config options, see the
+// README at: https://github.com/devcontainers/templates/tree/main/src/java
+{
+ "name": "Java",
+ // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
+ "image": "mcr.microsoft.com/devcontainers/java:21-bullseye",
+ "features": {
+ "ghcr.io/devcontainers/features/java:1": {
+ "jdkDistro": "ms",
+ "version": "21",
+ "installMaven": "true",
+ "installGradle": "false"
+ },
+ "ghcr.io/devcontainers/features/node:1": {
+ "version": "lts/Hydrogen"
+ },
+ "ghcr.io/devcontainers/features/python:1": {
+ "version": "3.10"
+ },
+ "ghcr.io/devcontainers-contrib/features/pre-commit:2": {
+ "version": "3.5.0"
+ },
+ "ghcr.io/devcontainers/features/common-utils:2.3.2": {}
+ },
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
+ // "forwardPorts": [],
+ // Use 'postCreateCommand' to run commands after the container is created.
+ "postCreateCommand": "",
+ // Configure tool-specific properties.
+ "customizations": {
+ "vscode": {
+ "settings": {
+ "maven.view": "hierarchical",
+ "java.compile.nullAnalysis.mode": "automatic",
+ "java.configuration.updateBuildConfiguration": "disabled",
+ "terminal.integrated.defaultProfile.linux": "zsh",
+ "terminal.integrated.profiles.linux": {
+ "zsh": {
+ "path": "/usr/bin/zsh"
+ }
+ }
+ },
+ "extensions": [
+ // add necessary extentions
+ ]
+ }
+ // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
+ // "remoteUser": "root"
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7ed409c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+target/
+.DS_Store
+.cli/
+.velocitas/
+.vscode/settings.json
+.attach*
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..fd16ba2
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,10 @@
+# See https://pre-commit.com for more information
+# See https://pre-commit.com/hooks.html for more hooks
+repos:
+- repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v3.2.0
+ hooks:
+ - id: trailing-whitespace
+ - id: end-of-file-fixer
+ - id: check-yaml
+ - id: check-added-large-files
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..e2da974
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,10 @@
+{
+ "configurations": [
+ {
+ "type": "java",
+ "name": "Launch Java Program",
+ "request": "launch",
+ "mainClass": "org.eclipse.vehicle_app.Main"
+ }
+ ]
+}
diff --git a/README.md b/README.md
index 3ea5da0..c6b76fe 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,31 @@
-# pkg-velocitas-uprotocol
\ No newline at end of file
+# Velocitas uProtocol Support package
+
+This repository is supposed to be used as a self-contained [Velocitas toolchain package](https://github.com/eclipse-velocitas/cli/blob/main/docs/features/PACKAGES.md) which enables
+the development of uProtocol applications and services (uApps and uServices). No further Velocitas packages are needed to develop uApps and uServices.
+
+
+## Setting up your local developoment environment
+
+Testing of the package shall be done in the `testbench` folder, where a `run_cli.sh` script is provided. This script will download and run the correct branch of the Velocitas CLI for the uProtocol integration using this repository as the package contents. This allows you to instantly test your package without further copying to other repos.
+
+
+## Structure
+
+The package is structured as follows, please follow the links for a detailed description of the component:
+
+* $root/
+ * 📁 components/
+ * 📁 cores/
+ * [project-creation-java](./components/cores/project-creation-java/README.md)/
+ * 📁 scripts/
+ * 📄 create.py
+ * 📁 templates/
+ * 📁 extensions/
+ * 📁 [devcontainer-setup-java](./components/extensions/devcontainer-setup-java/README.md)/
+ * 📁 [github-workflows](./components/extensions/github-workflows/README.md)/
+ * 📁 [service-catalogue-support](./components/extensions/service-catalogue-support/README.md)/ (?)
+ * 📁 [tool-manager](./components/extensions/tool-manager/README.md)/ (?)
+ * 📄 manager.py
+ * 📄 tools.yaml
+ * 📁 [testbench](./testbench/README.md)
+ * 📄 manifest.json
diff --git a/components/cores/project-creation-java/README.md b/components/cores/project-creation-java/README.md
new file mode 100644
index 0000000..35a1874
--- /dev/null
+++ b/components/cores/project-creation-java/README.md
@@ -0,0 +1,24 @@
+# Project Creation
+
+The core Velocitas toolchain component enables the project creation for uProtocol based projects. It contains scripts for creation of uApps/uServices, supporting all of uProtocols languages.
+
+## Supported project types
+
+* Empty skeleton
+* From example
+ * Horn activator
+
+## Interfaces
+
+### Service catalogue
+
+When creating a project based on the empty skeleton it is possible to specify a functional dependency on a catalogue of services to be used by the project. This catalogue consists of a file tree containing one or more protobuf service definitions.
+
+## Supported languages
+
+| Language | Status |
+|:--------:|:-------:|
+| Java | ✓ |
+| C++ | ✗ |
+| Rust | ✗ |
+| Kotlin | ✗ |
diff --git a/components/extensions/devcontainer-setup-java/README.md b/components/extensions/devcontainer-setup-java/README.md
new file mode 100644
index 0000000..bb6ead5
--- /dev/null
+++ b/components/extensions/devcontainer-setup-java/README.md
@@ -0,0 +1,9 @@
+# devContainer Setup Java
+
+Provides [devContainer](https://containers.dev/) configuration for Java based uApp/uService projects.
+This includes:
+
+* Basic tooling
+* Basic IDE configuration
+* Used extensions
+* Velocitas CLI
diff --git a/components/extensions/github-workflows/README.md b/components/extensions/github-workflows/README.md
new file mode 100644
index 0000000..54adeb9
--- /dev/null
+++ b/components/extensions/github-workflows/README.md
@@ -0,0 +1,11 @@
+# Github Workflows
+
+Provides Github CI/CD workflows for uApps/uServices.
+
+## Provided workflows:
+
+* CI for the uApps/uServices
+ * Build
+ * Unit tests
+ * Integration tests
+ * SCA
diff --git a/components/extensions/service-catalogue-support/README.md b/components/extensions/service-catalogue-support/README.md
new file mode 100644
index 0000000..a646b1e
--- /dev/null
+++ b/components/extensions/service-catalogue-support/README.md
@@ -0,0 +1,21 @@
+# Service Catalgoue Support
+
+Adds support for functional interfaces of a uApp/uService towards a service defined within a service catalogue (e.g. [COVESA uServices](https://github.com/COVESA/uservices/)). **Format below is not finalized and needs to be discussed once this toolchain component is developed.**
+
+**CONCEPT SHOULD BE ALIGNED WITH gRPC**
+
+
+## Usage in AppManifest.json
+
+```json
+{
+ "type": "service-catalogue-consumer",
+ "config": {
+ "src": "https://github.com/COVESA/uservices.git",
+ "services": [
+ "Chassis",
+ "Horn"
+ ]
+ }
+}
+```
diff --git a/components/extensions/tool-manager/README.md b/components/extensions/tool-manager/README.md
new file mode 100644
index 0000000..1df41d7
--- /dev/null
+++ b/components/extensions/tool-manager/README.md
@@ -0,0 +1,28 @@
+# Tool Manager
+
+A tool manager for uProtocol tools. At the moment the following are supported:
+
+* [uProtocol Simulator](https://github.com/eclipse-uprotocol/up-simulator)
+* [uP Client Android](https://github.com/eclipse-uprotocol/up-client-android-java)
+
+## Requirements
+
+The tool manager shall meet the following requirements:
+
+* it shall download the respective tools to the `$VELOCITAS_HOME` and make them available to the velocitas project via exposed programs. (e.g. `velocitas exec up-simulator`)
+
+* it shall read used tool versions from a configuration file stored in the project directory. (Could be stored in the `.velocitas.json`)
+
+e.g. (`.velocitas.json`)
+```json
+{
+ ...
+ "variables": {
+ "uprotocolSimulatorVersion": "0.0.1",
+ "ulinkAndroidBinderVersion": "0.1.0"
+ }
+}
+```
+
+* it shall provide a UI (could be terminal prompts) which shows upgradeable tools and allow updates
+easily
diff --git a/components/project-creation/integration/run.py b/components/project-creation/integration/run.py
new file mode 100644
index 0000000..16d38ed
--- /dev/null
+++ b/components/project-creation/integration/run.py
@@ -0,0 +1 @@
+print("Create a new uProtocol project from scratch or template!")
diff --git a/components/project-creation/template/.devcontainer/devcontainer.json b/components/project-creation/template/.devcontainer/devcontainer.json
new file mode 100644
index 0000000..deff346
--- /dev/null
+++ b/components/project-creation/template/.devcontainer/devcontainer.json
@@ -0,0 +1,50 @@
+// For format details, see https://aka.ms/devcontainer.json. For config options, see the
+// README at: https://github.com/devcontainers/templates/tree/main/src/java
+{
+ "name": "Java",
+ // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
+ "image": "mcr.microsoft.com/devcontainers/java:11-bullseye",
+ "features": {
+ "ghcr.io/devcontainers/features/java:1": {
+ "jdkDistro": "ms",
+ "version": "11",
+ "installMaven": "true",
+ "installGradle": "false"
+ },
+ "ghcr.io/devcontainers/features/node:1": {
+ "version": "lts/Hydrogen"
+ },
+ "ghcr.io/devcontainers/features/python:1": {
+ "version": "3.10"
+ },
+ "ghcr.io/devcontainers-contrib/features/pre-commit:2": {
+ "version": "3.5.0"
+ },
+ "ghcr.io/devcontainers/features/common-utils:2.3.2": {},
+ },
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
+ // "forwardPorts": [],
+ // Use 'postCreateCommand' to run commands after the container is created.
+ "postCreateCommand": "",
+ // Configure tool-specific properties.
+ "customizations": {
+ "vscode": {
+ "settings": {
+ "maven.view": "hierarchical",
+ "java.compile.nullAnalysis.mode": "automatic",
+ "java.configuration.updateBuildConfiguration": "disabled",
+ "terminal.integrated.defaultProfile.linux": "zsh",
+ "terminal.integrated.profiles.linux": {
+ "zsh": {
+ "path": "/usr/bin/zsh"
+ }
+ }
+ },
+ "extensions": [
+ // add necessary extentions
+ ]
+ }
+ // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
+ // "remoteUser": "root"
+ }
+}
diff --git a/components/project-creation/template/.velocitas.json b/components/project-creation/template/.velocitas.json
new file mode 100644
index 0000000..174fa98
--- /dev/null
+++ b/components/project-creation/template/.velocitas.json
@@ -0,0 +1,10 @@
+{
+ "packages": [
+ {
+ "name": "velocitas-uprotocol-core",
+ "version": "latest"
+ }
+ ],
+ "variables": {},
+ "cliVersion": "v0.6.3"
+}
diff --git a/components/project-creation/template/app/pom.xml b/components/project-creation/template/app/pom.xml
new file mode 100644
index 0000000..8a42fdb
--- /dev/null
+++ b/components/project-creation/template/app/pom.xml
@@ -0,0 +1,181 @@
+
+
+
+
+ 4.0.0
+
+ org.eclipse.vehicle_app
+ uprotocol-app
+ uProtocol Vehicle App
+ Velocitas Vehicle Application using uProtocol
+
+ ${revision}
+ jar
+
+
+ 11
+ UTF-8
+ 11
+ 11
+ UTF-8
+
+ 0.1
+
+ 1.9.1
+ 5.9.1
+ 4.12
+ 3.0.0-M5
+
+ 1.5.2
+ 1.5.4
+ 2.6.18
+
+
+
+
+
+ kr.motd.maven
+ os-maven-plugin
+ 1.6.2
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ ${java.version}
+
+ 3.10.1
+
+
+
+ org.apache.maven.plugins
+ maven-clean-plugin
+ 3.1.0
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 3.1.0
+
+
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+
+ false
+ ${argLine}
+
+
+
+ maven-jar-plugin
+ 3.0.2
+
+
+ maven-install-plugin
+ 2.5.2
+
+
+ maven-deploy-plugin
+ 2.8.2
+
+
+ org.apache.maven.plugins
+ maven-project-info-reports-plugin
+ 3.4.1
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.8
+
+
+
+ prepare-agent
+
+
+
+
+ report
+ test
+
+ report
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.4.1
+
+ all,-missing,-reference
+
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+
+
+
+
+
+ org.eclipse.uprotocol
+ uprotocol-core-api
+ ${uprotocol-core-api.version}
+
+
+
+
+ org.eclipse.uprotocol
+ uprotocol-java
+ ${uprotocol-java.version}
+
+
+
+
+ org.covesa.uservice
+ uservice
+ 0.1.0
+ system
+ /workspaces/velocitas-uprotocol-java/components/uservices/uservices-api-0.1.0-SNAPSHOT.jar
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit-jupiter.version}
+ test
+
+
+
+
+
+
+
+
+ com.google.protobuf
+ protobuf-java
+ 3.16.3
+
+
+
+
+
+
diff --git a/components/project-creation/template/app/src/main/java/org/eclipse/uprotocol/ulink/echo/ULink.java b/components/project-creation/template/app/src/main/java/org/eclipse/uprotocol/ulink/echo/ULink.java
new file mode 100644
index 0000000..cf2fa30
--- /dev/null
+++ b/components/project-creation/template/app/src/main/java/org/eclipse/uprotocol/ulink/echo/ULink.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2023 General Motors GTO LLC
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * SPDX-FileType: SOURCE
+ * SPDX-FileCopyrightText: 2023 General Motors GTO LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package org.eclipse.uprotocol.ulink.echo;
+
+import org.eclipse.uprotocol.transport.UTransport;
+import org.eclipse.uprotocol.transport.UListener;
+import org.eclipse.uprotocol.uri.validator.UriValidator;
+import org.eclipse.uprotocol.v1.*;
+import org.eclipse.uprotocol.validation.ValidationResult;
+
+import java.util.Map;
+
+import java.util.HashMap;
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.uprotocol.rpc.RpcClient;
+
+/* Simple example code that shows an echo transport */
+public class ULink implements UTransport, RpcClient {
+
+ private final Map mListeners = new HashMap<>();
+ private final Map> mRequests = new ConcurrentHashMap<>();
+ private Executor mExecutor;
+
+ // The following fakes ingress events and is called whenever send() is called
+ // since this is an echo uTransport and doesn't connect uEs together.
+ private final UListener mGenericListener = new UListener() {
+ @Override
+ public UStatus onReceive(UUri uri, UPayload payload, UAttributes attributes) {
+
+ switch (attributes.getType()) {
+ // Responses requires us to complete the future for the request to notify the
+ // client
+ case UMESSAGE_TYPE_RESPONSE:
+ final CompletableFuture responseFuture = mRequests.remove(attributes.getReqid());
+ if (responseFuture == null) {
+ UStatus.newBuilder()
+ .setCode(UCode.INTERNAL)
+ .setMessage("Request{id='" + attributes.getReqid().toString() + "'} already completed")
+ .build();
+ }
+
+ break;
+
+ default:
+ for (Map.Entry entry : mListeners.entrySet()) {
+ if (entry.getKey().equals(uri)) {
+ mExecutor.execute(() -> {
+ entry.getValue().onReceive(uri, payload, attributes);
+ });
+ }
+ }
+ break;
+ }
+ return UStatus.newBuilder().setCode(UCode.OK).build();
+ }
+ };
+
+ /*
+ * uLink constructor that takes in an executor to run the listener callbacks on
+ *
+ * @param executor - the executor to run the listener callbacks on
+ */
+ public ULink(Executor executor) {
+ Objects.requireNonNull(executor, "Executor cannot be null");
+ mExecutor = executor;
+ }
+
+ /*
+ * This simple invoke method will send the request and add a completable future
+ * to a list that will be completed when the response is received in the generic
+ * event handler.
+ *
+ * @param uri - the uri of the request
+ *
+ * @param payload - the payload of the request
+ *
+ * @param attributes - the attributes of the request
+ *
+ * @return CompletableFuture - the completed future with the response
+ */
+ @Override
+ public CompletableFuture invokeMethod(UUri uri, UPayload payload, UAttributes attributes) {
+ Objects.requireNonNull(uri, "Uri cannot be null");
+ Objects.requireNonNull(payload, "Payload cannot be null");
+ Objects.requireNonNull(attributes, "Attributes cannot be null");
+
+ return mRequests.compute(attributes.getId(), (requestId, currentRequest) -> {
+ // This is test code so we know it is always successful :-)
+ send(uri, payload, attributes);
+
+ return new CompletableFuture()
+ .orTimeout(attributes.getTtl(), TimeUnit.MILLISECONDS)
+ .whenComplete((responseData, exception) -> {
+ mRequests.remove(requestId);
+ });
+
+ });
+ }
+
+ /**
+ * Authenticator that always says you are authenticated, normally you need to
+ * validate the calling uE's identity matches that of entity
+ *
+ * @param entity - the entity to authenticate
+ */
+ @Override
+ public UStatus authenticate(UEntity entity) {
+ return UStatus.newBuilder().setCode(UCode.OK).build();
+ }
+
+ /**
+ * Register a listener that will be called when am event is reived. This method
+ * is used by services to register listeners for soon as you call send()
+ *
+ * @param uri - the uri to register the listener for
+ * @param listener - the listener to register
+ * @return UStatus - the status of the registration
+ */
+ @Override
+ public UStatus registerListener(UUri uri, UListener listener) {
+ ValidationResult result = UriValidator.validate(uri);
+ if (result.isFailure()) {
+ return UStatus.newBuilder()
+ .setCode(UCode.INVALID_ARGUMENT)
+ .setMessage(result.getMessage())
+ .build();
+ }
+
+ if (mListeners.containsKey(uri)) {
+ return UStatus.newBuilder()
+ .setCode(UCode.ALREADY_EXISTS)
+ .setMessage("Listener already registered for " + uri)
+ .build();
+ }
+
+ mListeners.put(uri, listener);
+
+ return UStatus.newBuilder().setCode(UCode.OK).build();
+ }
+
+ /**
+ * Send a message to the uri, this will call the listener that was registered
+ * for the uri to perform the loopback
+ */
+ @Override
+ public UStatus send(UUri uri, UPayload payload, UAttributes attributes) {
+ ValidationResult result = UriValidator.validate(uri);
+ if (result.isFailure()) {
+ return UStatus.newBuilder()
+ .setCode(UCode.INVALID_ARGUMENT)
+ .setMessage(result.getMessage())
+ .build();
+ }
+
+ // Trigger the callback to pretend that the event has looped back
+ mExecutor.execute(() -> {
+ mGenericListener.onReceive(uri, payload, attributes);
+ });
+
+ return UStatus.newBuilder().setCode(UCode.OK).build();
+ }
+
+ /**
+ * Unregister the listener for the uri
+ *
+ * @param uri - the uri to unregister the listener for
+ * @param listener - the listener to unregister
+ * @return UStatus - the status of the unregistration
+ */
+ @Override
+ public UStatus unregisterListener(UUri uri, UListener listener) {
+ ValidationResult result = UriValidator.validate(uri);
+ if (result.isFailure()) {
+ return UStatus.newBuilder()
+ .setCode(UCode.INVALID_ARGUMENT)
+ .setMessage(result.getMessage())
+ .build();
+ }
+
+ if (!mListeners.containsKey(uri)) {
+ return UStatus.newBuilder()
+ .setCode(UCode.INVALID_ARGUMENT)
+ .setMessage("No listener found for " + uri)
+ .build();
+ }
+
+ mListeners.remove(uri, listener);
+ return UStatus.newBuilder().setCode(UCode.OK).build();
+ }
+
+}
diff --git a/components/project-creation/template/app/src/main/java/org/eclipse/vehicle_app/App.java b/components/project-creation/template/app/src/main/java/org/eclipse/vehicle_app/App.java
new file mode 100644
index 0000000..1d3996a
--- /dev/null
+++ b/components/project-creation/template/app/src/main/java/org/eclipse/vehicle_app/App.java
@@ -0,0 +1,88 @@
+package org.eclipse.vehicle_app;
+
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Executor;
+
+import org.covesa.uservice.vehicle.body.horn.v1.ActivateHornRequest;
+import org.covesa.uservice.vehicle.body.horn.v1.HornMode;
+import org.eclipse.uprotocol.rpc.RpcMapper;
+import org.eclipse.uprotocol.rpc.RpcResult;
+import org.eclipse.uprotocol.transport.UListener;
+import org.eclipse.uprotocol.transport.builder.UAttributesBuilder;
+import org.eclipse.uprotocol.ulink.echo.ULink;
+import org.eclipse.uprotocol.uri.builder.UResourceBuilder;
+import org.eclipse.uprotocol.v1.UAttributes;
+import org.eclipse.uprotocol.v1.UCode;
+import org.eclipse.uprotocol.v1.UEntity;
+import org.eclipse.uprotocol.v1.UPayload;
+import org.eclipse.uprotocol.v1.UPayloadFormat;
+import org.eclipse.uprotocol.v1.UPriority;
+import org.eclipse.uprotocol.v1.UResource;
+import org.eclipse.uprotocol.v1.UStatus;
+import org.eclipse.uprotocol.v1.UUri;
+
+public class App {
+
+ public App() {
+ }
+
+ public void run() {
+ // request to be send
+ ActivateHornRequest request = ActivateHornRequest.newBuilder().setMode(HornMode.HM_CONTINUOUS).build();
+
+ final UUri mTopic = UUri.newBuilder()
+ .setEntity(UEntity.newBuilder().setName("body.horn").setVersionMajor(1))
+ .setResource(UResource.newBuilder().setName("hornstatus").setInstance("is_active").setMessage("true"))
+ .build();
+
+ final UPayload mPayload = UPayload.newBuilder()
+ .setValue(request.toByteString())
+ .setFormat(UPayloadFormat.UPAYLOAD_FORMAT_PROTOBUF)
+ .build();
+
+ final class MyListener implements UListener {
+ @Override
+ public UStatus onReceive(UUri uri, UPayload payload, UAttributes attributes) {
+ System.out.println("uri: " + uri);
+ System.out.println("payload: " + payload);
+ return UStatus.newBuilder().setCode(UCode.OK).build();
+ }
+ }
+
+ ULink ulink = new ULink(new Executor() {
+ @Override
+ public void execute(Runnable command) {
+ command.run();
+ }
+ });
+
+ ulink.registerListener(mTopic, new MyListener());
+
+ UAttributes attributes = UAttributesBuilder.publish(UPriority.UPRIORITY_CS4).build();
+
+ UStatus status = ulink.send(mTopic, mPayload, attributes);
+ System.out.println("Status: " + status.getCode());
+
+ // inovke rpc method
+
+ final UUri uri = UUri.newBuilder()
+ .setEntity(UEntity.newBuilder().setName("body.horn").setVersionMajor(1))
+ .setResource(UResourceBuilder.forRpcRequest("ActivateHorn")).build();
+
+ final UUri sink = UUri.newBuilder()
+ .setEntity(UEntity.newBuilder().setName("vehicle_app").setVersionMajor(1))
+ .setResource(UResourceBuilder.forRpcResponse()).build();
+
+ attributes = UAttributesBuilder.request(UPriority.UPRIORITY_CS1, sink, 1000).build();
+
+ // this is just with the test ULink which directly sends back the payload,
+ // normally one should expect the response accordingly
+ final CompletionStage> rpcResponse = RpcMapper.mapResponseToResult(
+ ulink.invokeMethod(uri, mPayload, attributes), ActivateHornRequest.class);
+
+ final CompletionStage test = rpcResponse.thenAccept(RpcResult -> {
+ System.out.println("RPC Result: " + RpcResult.isSuccess());
+ });
+ test.toCompletableFuture().join();
+ }
+}
diff --git a/components/project-creation/template/app/src/main/java/org/eclipse/vehicle_app/Main.java b/components/project-creation/template/app/src/main/java/org/eclipse/vehicle_app/Main.java
new file mode 100644
index 0000000..ff11fa5
--- /dev/null
+++ b/components/project-creation/template/app/src/main/java/org/eclipse/vehicle_app/Main.java
@@ -0,0 +1,8 @@
+package org.eclipse.vehicle_app;
+
+public class Main {
+ public static void main(String[] args) {
+ App myApp = new App();
+ myApp.run();
+ }
+}
diff --git a/components/uservices/uservices-api-0.1.0-SNAPSHOT.jar b/components/uservices/uservices-api-0.1.0-SNAPSHOT.jar
new file mode 100644
index 0000000..1459b92
Binary files /dev/null and b/components/uservices/uservices-api-0.1.0-SNAPSHOT.jar differ
diff --git a/launch.json b/launch.json
new file mode 100644
index 0000000..e2da974
--- /dev/null
+++ b/launch.json
@@ -0,0 +1,10 @@
+{
+ "configurations": [
+ {
+ "type": "java",
+ "name": "Launch Java Program",
+ "request": "launch",
+ "mainClass": "org.eclipse.vehicle_app.Main"
+ }
+ ]
+}
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..eda2f94
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,34 @@
+{
+ "components": [
+ {
+ "id": "project-creation-java",
+ "type": "core",
+ "programs": [
+ {
+ "id": "create-project",
+ "description": "Creates a new uProtocol project",
+ "executable": "python",
+ "args": "components/project-creation/integration/run.py"
+ }
+ ],
+ "variables": [
+ {
+ "id": "language",
+ "description": "Programming language of the project.",
+ "type": "string",
+ "scope": "project",
+ "constant": true,
+ "default": "java"
+ }
+ ]
+ },
+ {
+ "id": "devcontainer-setup-java",
+ "type": "extension",
+ "compatibleCores": [
+ "project-creation-java"
+ ],
+ "mandatory": true
+ }
+ ]
+}
diff --git a/testbench/README.md b/testbench/README.md
new file mode 100644
index 0000000..62b7225
--- /dev/null
+++ b/testbench/README.md
@@ -0,0 +1,3 @@
+# Testbench
+
+This directory acts as a root directory for all executed integration tests. It provides a uProtocol project-like file structure.
diff --git a/testbench/app/AppManifest.json b/testbench/app/AppManifest.json
new file mode 100644
index 0000000..ebace44
--- /dev/null
+++ b/testbench/app/AppManifest.json
@@ -0,0 +1,12 @@
+{
+ "manifestVersion": "v3",
+ "name": "My testable uApp",
+ "interfaces": [
+ {
+ "type": "service-catalogue-consumer",
+ "config": {
+ "src": "https://github.com/COVESA/uservices.git"
+ }
+ }
+ ]
+}
diff --git a/testbench/package-index.json b/testbench/package-index.json
new file mode 100644
index 0000000..3129001
--- /dev/null
+++ b/testbench/package-index.json
@@ -0,0 +1,176 @@
+[
+ {
+ "package": "https://github.com/eclipse-velocitas/vehicle-app-python-sdk",
+ "exposedInterfaces": [
+ {
+ "id": "vehicle-app-python-core",
+ "type": "core",
+ "name": "Velocitas Vehicle App (Python)",
+ "description": "Creates a Vehicle App written in Python",
+ "parameterSets": [
+ {
+ "id": "from-example",
+ "name": "Create an application from an example",
+ "parameters": [
+ {
+ "id": "example",
+ "description": "Provided Examples from SDK",
+ "type": "single-choice",
+ "required": true,
+ "values": [
+ {
+ "id": "seat-adjuster",
+ "description": "Seat Adjuster Example"
+ },
+ {
+ "id": "dog-mode",
+ "description": "Dog Mode Example"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "from-skeleton",
+ "name": "Create an application from scratch",
+ "parameters": [
+ {
+ "id": "name",
+ "required": true,
+ "description": "Name of your application",
+ "type": "string"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "package": "https://github.com/eclipse-velocitas/uprotocol-java-core",
+ "exposedInterfaces": [
+ {
+ "id": "uprotocol-java-core",
+ "type": "core",
+ "name": "uProtocol App/Service (Java)",
+ "description": "Creates a uProtocol Application or Service written in Java",
+ "parameterSets": [
+ {
+ "id": "from-example",
+ "name": "Create an application from an example",
+ "parameters": [
+ {
+ "id": "example",
+ "description": "Provided Examples from SDK",
+ "type": "single-choice",
+ "required": true,
+ "values": [
+ {
+ "id": "seat-adjuster",
+ "description": "Seat Adjuster Example"
+ },
+ {
+ "id": "dog-mode",
+ "description": "Dog Mode Example"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "from-skeleton",
+ "name": "Create an application from scratch",
+ "parameters": [
+ {
+ "id": "name",
+ "required": true,
+ "description": "Name of your application",
+ "type": "string"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "package": "https://github.com/eclipse-velocitas/devenv-devcontainer-setup.git",
+ "exposedInterfaces": [
+ {
+ "id": "vehicle-signal-interface",
+ "type": "extension",
+ "name": "Vehicle Signal Interface",
+ "description": "Vehicle Signal Interface based on VSS and KUKSA Databroker",
+ "compatibleCores": [
+ "vehicle-app-python-core"
+ ],
+ "parameters": [
+ {
+ "id": "src",
+ "description": "URI or path to VSS json (Leave empty for default: v3.0)",
+ "default": "https://github.com/COVESA/vehicle_signal_specification/releases/download/v3.0/vss_rel_3.0.json",
+ "required": true,
+ "type": "string"
+ },
+ {
+ "id": "datapoints",
+ "description": "Datapoints to be used in your Vehicle Application",
+ "default": "{\"required\":[{\"path\":\"\",\"access\":\"\"}]}",
+ "required": false,
+ "type": "object"
+ }
+ ]
+ },
+ {
+ "id": "grpc-interface",
+ "type": "extension",
+ "name": "gRPC Service Contract",
+ "description": "gRPC service contract based on a proto interface description",
+ "compatibleCores": [
+ "vehicle-app-python-core"
+ ],
+ "parameters": [
+ {
+ "id": "src",
+ "description": "URI to the proto file which acts as the service interface",
+ "default": "",
+ "required": true,
+ "type": "string"
+ },
+ {
+ "id": "required",
+ "description": "Configuration for the \"Client\" of the service. (Leave empty for now)",
+ "required": false,
+ "default": "{}",
+ "type": "object"
+ },
+ {
+ "id": "provided",
+ "description": "Configuration for the \"Provider\" of the service. (Leave empty for now)",
+ "required": false,
+ "default": "{}",
+ "type": "object"
+ }
+ ]
+ },
+ {
+ "id": "uservice-interface",
+ "type": "extension",
+ "name": "uService Catalogue",
+ "description": "",
+ "compatibleCores": [
+ "uprotocol-java-core"
+ ],
+ "parameters": [
+ {
+ "id": "repo",
+ "description": "uServices repository",
+ "default": "https://github.com/COVESA/uservices.git",
+ "required": true,
+ "type": "string"
+ }
+ ]
+ }
+ ]
+ }
+]
diff --git a/testbench/run_cli.sh b/testbench/run_cli.sh
new file mode 100755
index 0000000..b6ea919
--- /dev/null
+++ b/testbench/run_cli.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+set -x
+
+export VELOCITAS_HOME=$(pwd)
+CLI_FOLDER=.cli
+
+if [ ! -e "${CLI_FOLDER}" ]; then
+ # Clone
+ git clone https://github.com/eclipse-velocitas/cli.git $CLI_FOLDER
+ # Fix dubious ownership
+ git config --global --add safe.directory $(pwd)/$CLI_FOLDER
+fi
+
+cd $CLI_FOLDER
+git switch feature/core-and-ext-pkg
+cp testbench/test-create/vehicle-app-template/package-index.json ../package-index.json
+
+if [ ! hash node &> /dev/null ]; then
+ ./install_node.sh
+fi
+
+npm i
+cd ..
+
+./${CLI_FOLDER}/bin/dev $@