From 2db03d0b5f8f2c45f0c2a335222984db020eb976 Mon Sep 17 00:00:00 2001 From: Andre Weber Date: Wed, 18 Dec 2024 07:17:15 +0100 Subject: [PATCH 1/9] test: Fix Failing Daily Integration Tests --- ...tegration_main-master.yaml => daily_integration_main.yaml} | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename .github/workflows/{daily_integration_main-master.yaml => daily_integration_main.yaml} (85%) diff --git a/.github/workflows/daily_integration_main-master.yaml b/.github/workflows/daily_integration_main.yaml similarity index 85% rename from .github/workflows/daily_integration_main-master.yaml rename to .github/workflows/daily_integration_main.yaml index e6cf117..b4558cc 100644 --- a/.github/workflows/daily_integration_main-master.yaml +++ b/.github/workflows/daily_integration_main.yaml @@ -1,4 +1,4 @@ -name: SDK:main <-> Databroker:master +name: SDK:main <-> Databroker:main on: schedule: @@ -20,5 +20,5 @@ jobs: uses: ./.github/actions/run-tests with: upload-test-reports: true - databroker-version: master + databroker-version: main kotest-tag: "Integration" diff --git a/README.md b/README.md index f2d131b..3dc320a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0) [![Gitter](https://img.shields.io/gitter/room/kuksa-val/community)](https://gitter.im/kuksa-val/community) -[![SDK:main <-> Databroker:master](https://github.com/eclipse-kuksa/kuksa-java-sdk/actions/workflows/daily_integration_main-master.yaml/badge.svg)](https://github.com/eclipse-kuksa/kuksa-java-sdk/actions/workflows/daily_integration_main-master.yaml?query=branch%3Amain) +[![SDK:main <-> Databroker:main](https://github.com/eclipse-kuksa/kuksa-java-sdk/actions/workflows/daily_integration_main.yaml/badge.svg)](https://github.com/eclipse-kuksa/kuksa-java-sdk/actions/workflows/daily_integration_main.yaml?query=branch%3Amain) This is a Java SDK for the [KUKSA Vehicle Abstraction Layer](https://github.com/eclipse-kuksa/kuksa-databroker). From 2f0baa4e34f7202059b95cacdde47e9b2fe6cc61 Mon Sep 17 00:00:00 2001 From: Andre Weber Date: Thu, 9 Jan 2025 09:23:25 +0100 Subject: [PATCH 2/9] chore: Move Kuksa Val V1 stuff in v1 folder --- .../{listener => }/DisconnectListener.kt | 5 ++-- .../{ => v1}/DataBrokerConnection.kt | 28 ++++++++++--------- .../{ => v1}/DataBrokerConnector.kt | 6 ++-- .../{ => v1}/DataBrokerTransporter.kt | 10 ++++--- .../v1/extension}/VALStubExtension.kt | 6 ++-- .../{ => v1}/listener/VssPathListener.kt | 2 +- .../{ => v1}/request/DataBrokerRequest.kt | 2 +- .../{ => v1}/request/FetchRequest.kt | 7 +++-- .../{ => v1}/request/SubscribeRequest.kt | 7 +++-- .../{ => v1}/request/UpdateRequest.kt | 7 +++-- .../request/VssNodeDataBrokerRequest.kt | 7 +++-- .../{ => v1}/request/VssNodeFetchRequest.kt | 7 +++-- .../request/VssNodeSubscribeRequest.kt | 7 +++-- .../{ => v1}/request/VssNodeUpdateRequest.kt | 7 +++-- .../response/VssNodeUpdateResponse.kt | 2 +- .../subscription/DataBrokerSubscriber.kt | 8 +++--- .../subscription/DataBrokerSubscription.kt | 4 +-- .../subscription/VssNodePathListener.kt | 6 ++-- .../DataBrokerConnectorAuthenticationTest.kt | 6 ++-- .../databroker/DataBrokerConnectionTest.kt | 18 ++++++------ .../databroker/DataBrokerConnectorProvider.kt | 1 + .../databroker/DataBrokerTransporterTest.kt | 3 +- .../subscription/DataBrokerSubscriberTest.kt | 6 ++-- .../DataBrokerTransporterExtensions.kt | 2 +- .../kuksa/mocking/FriendlyVssNodeListener.kt | 2 +- .../kuksa/mocking/FriendlyVssPathListener.kt | 2 +- 26 files changed, 95 insertions(+), 73 deletions(-) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{listener => }/DisconnectListener.kt (90%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/DataBrokerConnection.kt (90%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/DataBrokerConnector.kt (94%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/DataBrokerTransporter.kt (94%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/{authentication => databroker/v1/extension}/VALStubExtension.kt (89%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/listener/VssPathListener.kt (97%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/request/DataBrokerRequest.kt (95%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/request/FetchRequest.kt (83%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/request/SubscribeRequest.kt (83%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/request/UpdateRequest.kt (84%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/request/VssNodeDataBrokerRequest.kt (83%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/request/VssNodeFetchRequest.kt (83%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/request/VssNodeSubscribeRequest.kt (83%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/request/VssNodeUpdateRequest.kt (83%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/response/VssNodeUpdateResponse.kt (94%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/subscription/DataBrokerSubscriber.kt (94%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/subscription/DataBrokerSubscription.kt (94%) rename kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/subscription/VssNodePathListener.kt (89%) diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/listener/DisconnectListener.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/DisconnectListener.kt similarity index 90% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/listener/DisconnectListener.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/DisconnectListener.kt index ae8e4fa..f185126 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/listener/DisconnectListener.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/DisconnectListener.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,10 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker.listener +package org.eclipse.kuksa.connectivity.databroker import org.eclipse.kuksa.pattern.listener.Listener diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnection.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnection.kt similarity index 90% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnection.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnection.kt index 65b9abb..6b59a00 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnection.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnection.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,10 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker +package org.eclipse.kuksa.connectivity.databroker.v1 import io.grpc.ConnectivityState import io.grpc.ManagedChannel @@ -24,17 +25,18 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.eclipse.kuksa.connectivity.authentication.JsonWebToken -import org.eclipse.kuksa.connectivity.databroker.listener.DisconnectListener -import org.eclipse.kuksa.connectivity.databroker.listener.VssNodeListener -import org.eclipse.kuksa.connectivity.databroker.listener.VssPathListener -import org.eclipse.kuksa.connectivity.databroker.request.FetchRequest -import org.eclipse.kuksa.connectivity.databroker.request.SubscribeRequest -import org.eclipse.kuksa.connectivity.databroker.request.UpdateRequest -import org.eclipse.kuksa.connectivity.databroker.request.VssNodeFetchRequest -import org.eclipse.kuksa.connectivity.databroker.request.VssNodeSubscribeRequest -import org.eclipse.kuksa.connectivity.databroker.request.VssNodeUpdateRequest -import org.eclipse.kuksa.connectivity.databroker.response.VssNodeUpdateResponse -import org.eclipse.kuksa.connectivity.databroker.subscription.DataBrokerSubscriber +import org.eclipse.kuksa.connectivity.databroker.DataBrokerException +import org.eclipse.kuksa.connectivity.databroker.DisconnectListener +import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssNodeListener +import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssPathListener +import org.eclipse.kuksa.connectivity.databroker.v1.request.FetchRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.SubscribeRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.UpdateRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.VssNodeFetchRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.VssNodeSubscribeRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.VssNodeUpdateRequest +import org.eclipse.kuksa.connectivity.databroker.v1.response.VssNodeUpdateResponse +import org.eclipse.kuksa.connectivity.databroker.v1.subscription.DataBrokerSubscriber import org.eclipse.kuksa.extension.TAG import org.eclipse.kuksa.extension.datapoint import org.eclipse.kuksa.extension.vss.copy diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnector.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnector.kt similarity index 94% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnector.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnector.kt index f34b530..6738412 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnector.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnector.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,10 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker +package org.eclipse.kuksa.connectivity.databroker.v1 import io.grpc.ConnectivityState import io.grpc.ManagedChannel @@ -25,6 +26,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.withContext import org.eclipse.kuksa.connectivity.authentication.JsonWebToken +import org.eclipse.kuksa.connectivity.databroker.DataBrokerException import org.eclipse.kuksa.extension.TAG import org.eclipse.kuksa.model.TimeoutConfig import java.util.logging.Logger diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerTransporter.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerTransporter.kt similarity index 94% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerTransporter.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerTransporter.kt index e415c21..06966a2 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerTransporter.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerTransporter.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,10 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker +package org.eclipse.kuksa.connectivity.databroker.v1 import io.grpc.ConnectivityState import io.grpc.Context @@ -27,8 +28,9 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.eclipse.kuksa.connectivity.authentication.JsonWebToken -import org.eclipse.kuksa.connectivity.authentication.withAuthenticationInterceptor -import org.eclipse.kuksa.connectivity.databroker.subscription.DataBrokerSubscription +import org.eclipse.kuksa.connectivity.databroker.DataBrokerException +import org.eclipse.kuksa.connectivity.databroker.v1.extension.withAuthenticationInterceptor +import org.eclipse.kuksa.connectivity.databroker.v1.subscription.DataBrokerSubscription import org.eclipse.kuksa.extension.TAG import org.eclipse.kuksa.extension.applyDatapoint import org.eclipse.kuksa.proto.v1.KuksaValV1 diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/authentication/VALStubExtension.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/extension/VALStubExtension.kt similarity index 89% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/authentication/VALStubExtension.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/extension/VALStubExtension.kt index be14d9b..2d941fa 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/authentication/VALStubExtension.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/extension/VALStubExtension.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,16 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.authentication +package org.eclipse.kuksa.connectivity.databroker.v1.extension import com.google.common.net.HttpHeaders import io.grpc.ClientInterceptor import io.grpc.Metadata import io.grpc.stub.MetadataUtils +import org.eclipse.kuksa.connectivity.authentication.JsonWebToken import org.eclipse.kuksa.proto.v1.VALGrpc.VALBlockingStub import org.eclipse.kuksa.proto.v1.VALGrpc.VALStub diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/listener/VssPathListener.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/listener/VssPathListener.kt similarity index 97% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/listener/VssPathListener.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/listener/VssPathListener.kt index 90401c0..141f47e 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/listener/VssPathListener.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/listener/VssPathListener.kt @@ -16,7 +16,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.eclipse.kuksa.connectivity.databroker.listener +package org.eclipse.kuksa.connectivity.databroker.v1.listener import org.eclipse.kuksa.pattern.listener.Listener import org.eclipse.kuksa.proto.v1.KuksaValV1 diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/DataBrokerRequest.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/DataBrokerRequest.kt similarity index 95% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/DataBrokerRequest.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/DataBrokerRequest.kt index dfb44e1..6dd4bc5 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/DataBrokerRequest.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/DataBrokerRequest.kt @@ -16,7 +16,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.eclipse.kuksa.connectivity.databroker.request +package org.eclipse.kuksa.connectivity.databroker.v1.request import org.eclipse.kuksa.proto.v1.Types.Field import org.eclipse.kuksa.proto.v1.Types.Field.FIELD_VALUE diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/FetchRequest.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/FetchRequest.kt similarity index 83% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/FetchRequest.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/FetchRequest.kt index db7a7cc..befaaea 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/FetchRequest.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/FetchRequest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,15 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker.request +package org.eclipse.kuksa.connectivity.databroker.v1.request import org.eclipse.kuksa.proto.v1.Types /** - * Used for fetch requests with [org.eclipse.kuksa.connectivity.databroker.DataBrokerConnection.fetch]. + * Used for fetch requests with [org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnection.fetch]. */ open class FetchRequest @JvmOverloads constructor( override val vssPath: String, diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/SubscribeRequest.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/SubscribeRequest.kt similarity index 83% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/SubscribeRequest.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/SubscribeRequest.kt index f020159..6b601ed 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/SubscribeRequest.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/SubscribeRequest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,15 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker.request +package org.eclipse.kuksa.connectivity.databroker.v1.request import org.eclipse.kuksa.proto.v1.Types /** - * Used for subscribe requests with [org.eclipse.kuksa.connectivity.databroker.DataBrokerConnection.subscribe]. + * Used for subscribe requests with [org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnection.subscribe]. */ open class SubscribeRequest @JvmOverloads constructor( override val vssPath: String, diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/UpdateRequest.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/UpdateRequest.kt similarity index 84% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/UpdateRequest.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/UpdateRequest.kt index 310b6c4..0ed22dd 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/UpdateRequest.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/UpdateRequest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,15 +14,16 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker.request +package org.eclipse.kuksa.connectivity.databroker.v1.request import org.eclipse.kuksa.proto.v1.Types import org.eclipse.kuksa.proto.v1.Types.Datapoint /** - * Used for update requests with [org.eclipse.kuksa.connectivity.databroker.DataBrokerConnection.update]. + * Used for update requests with [org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnection.update]. */ open class UpdateRequest @JvmOverloads constructor( override val vssPath: String, diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/VssNodeDataBrokerRequest.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/VssNodeDataBrokerRequest.kt similarity index 83% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/VssNodeDataBrokerRequest.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/VssNodeDataBrokerRequest.kt index c4afd34..1274a4f 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/VssNodeDataBrokerRequest.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/VssNodeDataBrokerRequest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,15 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker.request +package org.eclipse.kuksa.connectivity.databroker.v1.request import org.eclipse.kuksa.vsscore.model.VssNode /** - * Uses [VssNode] models to request information for the [org.eclipse.kuksa.connectivity.databroker.DataBrokerConnection] + * Uses [VssNode] models to request information for the [org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnection] * which are generated by the [org.eclipse.kuksa.vsscore.annotation.VssModelGenerator]. */ interface VssNodeDataBrokerRequest : DataBrokerRequest { diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/VssNodeFetchRequest.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/VssNodeFetchRequest.kt similarity index 83% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/VssNodeFetchRequest.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/VssNodeFetchRequest.kt index 6e0f3ab..e2721dd 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/VssNodeFetchRequest.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/VssNodeFetchRequest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,16 +14,17 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker.request +package org.eclipse.kuksa.connectivity.databroker.v1.request import org.eclipse.kuksa.proto.v1.Types import org.eclipse.kuksa.vsscore.model.VssNode /** * Used for fetch requests with a generated [VssNode] model and - * [org.eclipse.kuksa.connectivity.databroker.DataBrokerConnection.fetch]. + * [org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnection.fetch]. */ class VssNodeFetchRequest @JvmOverloads constructor( override val vssNode: T, diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/VssNodeSubscribeRequest.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/VssNodeSubscribeRequest.kt similarity index 83% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/VssNodeSubscribeRequest.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/VssNodeSubscribeRequest.kt index 76a806a..4f6f0fb 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/VssNodeSubscribeRequest.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/VssNodeSubscribeRequest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,16 +14,17 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker.request +package org.eclipse.kuksa.connectivity.databroker.v1.request import org.eclipse.kuksa.proto.v1.Types import org.eclipse.kuksa.vsscore.model.VssNode /** * Used for subscribe requests with a generated [VssNode] model and - * [org.eclipse.kuksa.connectivity.databroker.DataBrokerConnection.subscribe]. + * [org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnection.subscribe]. */ class VssNodeSubscribeRequest @JvmOverloads constructor( override val vssNode: T, diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/VssNodeUpdateRequest.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/VssNodeUpdateRequest.kt similarity index 83% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/VssNodeUpdateRequest.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/VssNodeUpdateRequest.kt index fb8d69d..a332615 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/request/VssNodeUpdateRequest.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/request/VssNodeUpdateRequest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,16 +14,17 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker.request +package org.eclipse.kuksa.connectivity.databroker.v1.request import org.eclipse.kuksa.proto.v1.Types import org.eclipse.kuksa.vsscore.model.VssNode /** * Used for update requests with a generated [VssNode] model and - * [org.eclipse.kuksa.connectivity.databroker.DataBrokerConnection.update]. + * [org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnection.update]. */ class VssNodeUpdateRequest @JvmOverloads constructor( override val vssNode: T, diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/response/VssNodeUpdateResponse.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/response/VssNodeUpdateResponse.kt similarity index 94% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/response/VssNodeUpdateResponse.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/response/VssNodeUpdateResponse.kt index 0599373..2bdab29 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/response/VssNodeUpdateResponse.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/response/VssNodeUpdateResponse.kt @@ -16,7 +16,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.eclipse.kuksa.connectivity.databroker.response +package org.eclipse.kuksa.connectivity.databroker.v1.response import org.eclipse.kuksa.proto.v1.KuksaValV1.SetResponse diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/DataBrokerSubscriber.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/subscription/DataBrokerSubscriber.kt similarity index 94% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/DataBrokerSubscriber.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/subscription/DataBrokerSubscriber.kt index 816a270..9996bfe 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/DataBrokerSubscriber.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/subscription/DataBrokerSubscriber.kt @@ -16,12 +16,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.eclipse.kuksa.connectivity.databroker.subscription +package org.eclipse.kuksa.connectivity.databroker.v1.subscription import org.eclipse.kuksa.connectivity.databroker.DataBrokerException -import org.eclipse.kuksa.connectivity.databroker.DataBrokerTransporter -import org.eclipse.kuksa.connectivity.databroker.listener.VssNodeListener -import org.eclipse.kuksa.connectivity.databroker.listener.VssPathListener +import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerTransporter +import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssNodeListener +import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssPathListener import org.eclipse.kuksa.extension.TAG import org.eclipse.kuksa.proto.v1.Types import org.eclipse.kuksa.proto.v1.Types.Field diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/DataBrokerSubscription.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/subscription/DataBrokerSubscription.kt similarity index 94% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/DataBrokerSubscription.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/subscription/DataBrokerSubscription.kt index 461b737..c41d633 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/DataBrokerSubscription.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/subscription/DataBrokerSubscription.kt @@ -16,10 +16,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.eclipse.kuksa.connectivity.databroker.subscription +package org.eclipse.kuksa.connectivity.databroker.v1.subscription import io.grpc.Context -import org.eclipse.kuksa.connectivity.databroker.listener.VssPathListener +import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssPathListener import org.eclipse.kuksa.pattern.listener.MultiListener import org.eclipse.kuksa.proto.v1.KuksaValV1.SubscribeResponse import org.eclipse.kuksa.proto.v1.Types.Field diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/VssNodePathListener.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/subscription/VssNodePathListener.kt similarity index 89% rename from kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/VssNodePathListener.kt rename to kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/subscription/VssNodePathListener.kt index 4c078a4..7f55f34 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/VssNodePathListener.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/subscription/VssNodePathListener.kt @@ -16,10 +16,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.eclipse.kuksa.connectivity.databroker.subscription +package org.eclipse.kuksa.connectivity.databroker.v1.subscription -import org.eclipse.kuksa.connectivity.databroker.listener.VssNodeListener -import org.eclipse.kuksa.connectivity.databroker.listener.VssPathListener +import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssNodeListener +import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssPathListener import org.eclipse.kuksa.extension.vss.copy import org.eclipse.kuksa.proto.v1.KuksaValV1 import org.eclipse.kuksa.vsscore.model.VssNode diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/authentication/DataBrokerConnectorAuthenticationTest.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/authentication/DataBrokerConnectorAuthenticationTest.kt index 232d291..d292b66 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/authentication/DataBrokerConnectorAuthenticationTest.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/authentication/DataBrokerConnectorAuthenticationTest.kt @@ -30,9 +30,9 @@ import org.eclipse.kuksa.connectivity.databroker.DataBrokerConnectorProvider import org.eclipse.kuksa.connectivity.databroker.DataBrokerException import org.eclipse.kuksa.connectivity.databroker.docker.DataBrokerDockerContainer import org.eclipse.kuksa.connectivity.databroker.docker.SecureDataBrokerDockerContainer -import org.eclipse.kuksa.connectivity.databroker.request.FetchRequest -import org.eclipse.kuksa.connectivity.databroker.request.SubscribeRequest -import org.eclipse.kuksa.connectivity.databroker.request.UpdateRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.FetchRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.SubscribeRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.UpdateRequest import org.eclipse.kuksa.mocking.FriendlyVssPathListener import org.eclipse.kuksa.proto.v1.Types import org.eclipse.kuksa.test.kotest.Authentication diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectionTest.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectionTest.kt index 4551e05..58762f7 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectionTest.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectionTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ package org.eclipse.kuksa.connectivity.databroker @@ -29,13 +30,14 @@ import io.mockk.mockk import io.mockk.verify import org.eclipse.kuksa.connectivity.databroker.docker.DataBrokerDockerContainer import org.eclipse.kuksa.connectivity.databroker.docker.InsecureDataBrokerDockerContainer -import org.eclipse.kuksa.connectivity.databroker.listener.DisconnectListener -import org.eclipse.kuksa.connectivity.databroker.request.FetchRequest -import org.eclipse.kuksa.connectivity.databroker.request.SubscribeRequest -import org.eclipse.kuksa.connectivity.databroker.request.UpdateRequest -import org.eclipse.kuksa.connectivity.databroker.request.VssNodeFetchRequest -import org.eclipse.kuksa.connectivity.databroker.request.VssNodeSubscribeRequest -import org.eclipse.kuksa.connectivity.databroker.request.VssNodeUpdateRequest +import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnection +import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerTransporter +import org.eclipse.kuksa.connectivity.databroker.v1.request.FetchRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.SubscribeRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.UpdateRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.VssNodeFetchRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.VssNodeSubscribeRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.VssNodeUpdateRequest import org.eclipse.kuksa.extensions.updateRandomFloatValue import org.eclipse.kuksa.mocking.FriendlyVssNodeListener import org.eclipse.kuksa.mocking.FriendlyVssPathListener diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectorProvider.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectorProvider.kt index 2e78166..63ee1a6 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectorProvider.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectorProvider.kt @@ -27,6 +27,7 @@ import org.eclipse.kuksa.connectivity.authentication.JsonWebToken import org.eclipse.kuksa.connectivity.authentication.JwtType import org.eclipse.kuksa.connectivity.databroker.docker.DEFAULT_PORT_INSECURE import org.eclipse.kuksa.connectivity.databroker.docker.DEFAULT_PORT_SECURE +import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnector import org.eclipse.kuksa.model.TimeoutConfig import org.eclipse.kuksa.test.TestResourceFile import java.io.IOException diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerTransporterTest.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerTransporterTest.kt index 733b868..fa546ac 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerTransporterTest.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerTransporterTest.kt @@ -28,7 +28,8 @@ import io.mockk.mockk import io.mockk.verify import org.eclipse.kuksa.connectivity.databroker.docker.DataBrokerDockerContainer import org.eclipse.kuksa.connectivity.databroker.docker.InsecureDataBrokerDockerContainer -import org.eclipse.kuksa.connectivity.databroker.listener.VssPathListener +import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerTransporter +import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssPathListener import org.eclipse.kuksa.extensions.updateRandomFloatValue import org.eclipse.kuksa.mocking.FriendlyVssPathListener import org.eclipse.kuksa.proto.v1.KuksaValV1 diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/DataBrokerSubscriberTest.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/DataBrokerSubscriberTest.kt index d065c32..5f3acae 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/DataBrokerSubscriberTest.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/DataBrokerSubscriberTest.kt @@ -28,10 +28,12 @@ import io.mockk.every import io.mockk.mockk import io.mockk.verify import org.eclipse.kuksa.connectivity.databroker.DataBrokerConnectorProvider -import org.eclipse.kuksa.connectivity.databroker.DataBrokerTransporter import org.eclipse.kuksa.connectivity.databroker.docker.DataBrokerDockerContainer import org.eclipse.kuksa.connectivity.databroker.docker.InsecureDataBrokerDockerContainer -import org.eclipse.kuksa.connectivity.databroker.listener.VssPathListener +import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerTransporter +import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssPathListener +import org.eclipse.kuksa.connectivity.databroker.v1.subscription.DataBrokerSubscriber +import org.eclipse.kuksa.connectivity.databroker.v1.subscription.DataBrokerSubscription import org.eclipse.kuksa.extensions.toggleBoolean import org.eclipse.kuksa.extensions.updateRandomFloatValue import org.eclipse.kuksa.extensions.updateRandomUint32Value diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/extensions/DataBrokerTransporterExtensions.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/extensions/DataBrokerTransporterExtensions.kt index 4f85f2f..c4aceb1 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/extensions/DataBrokerTransporterExtensions.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/extensions/DataBrokerTransporterExtensions.kt @@ -20,7 +20,7 @@ package org.eclipse.kuksa.extensions import io.kotest.assertions.fail -import org.eclipse.kuksa.connectivity.databroker.DataBrokerTransporter +import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerTransporter import org.eclipse.kuksa.proto.v1.Types import kotlin.random.Random diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/mocking/FriendlyVssNodeListener.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/mocking/FriendlyVssNodeListener.kt index ce4c7ac..faa962a 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/mocking/FriendlyVssNodeListener.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/mocking/FriendlyVssNodeListener.kt @@ -19,7 +19,7 @@ package org.eclipse.kuksa.mocking -import org.eclipse.kuksa.connectivity.databroker.listener.VssNodeListener +import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssNodeListener import org.eclipse.kuksa.vsscore.model.VssNode class FriendlyVssNodeListener : VssNodeListener { diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/mocking/FriendlyVssPathListener.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/mocking/FriendlyVssPathListener.kt index b335409..9f0584c 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/mocking/FriendlyVssPathListener.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/mocking/FriendlyVssPathListener.kt @@ -19,7 +19,7 @@ package org.eclipse.kuksa.mocking -import org.eclipse.kuksa.connectivity.databroker.listener.VssPathListener +import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssPathListener import org.eclipse.kuksa.proto.v1.KuksaValV1 class FriendlyVssPathListener : VssPathListener { From b2a33e516846d5c1ad849afe521f1d339ac1d606 Mon Sep 17 00:00:00 2001 From: Andre Weber Date: Thu, 9 Jan 2025 09:24:33 +0100 Subject: [PATCH 3/9] feature: Add Support for kuksa.val.v2 Protocol --- gradle/libs.versions.toml | 5 + kuksa-java-sdk/build.gradle.kts | 36 +- .../databroker/v2/DataBrokerConnectionV2.kt | 207 ++++++++++++ .../databroker/v2/DataBrokerConnectorV2.kt | 90 +++++ .../databroker/v2/DataBrokerTransporterV2.kt | 309 ++++++++++++++++++ .../v2/extension/VALStubExtension.kt | 45 +++ .../src/main/proto/kuksa/val/v2/types.proto | 229 +++++++++++++ .../src/main/proto/kuksa/val/v2/val.proto | 297 +++++++++++++++++ 8 files changed, 1205 insertions(+), 13 deletions(-) create mode 100644 kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2.kt create mode 100644 kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectorV2.kt create mode 100644 kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerTransporterV2.kt create mode 100644 kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extension/VALStubExtension.kt create mode 100644 kuksa-java-sdk/src/main/proto/kuksa/val/v2/types.proto create mode 100644 kuksa-java-sdk/src/main/proto/kuksa/val/v2/val.proto diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 47184c0..050e3eb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,6 +7,7 @@ kotlin = "1.9.22" tomcatAnnotations = "6.0.53" ktlint = "0.0" # Maintained inside ktlint.gradle.kts grpc = "1.65.1" +grpcKotlin = "1.4.1" protobufGradlePlugin = "0.9.4" protobuf = "3.25.3" kotest = "5.7.2" @@ -20,6 +21,10 @@ docker-java-transport-httpclient5 = { module = "com.github.docker-java:docker-ja grpc-okhttp = { group = "io.grpc", name = "grpc-okhttp", version.ref = "grpc" } grpc-protobuf = { group = "io.grpc", name = "grpc-protobuf-lite", version.ref = "grpc" } grpc-stub = { group = "io.grpc", name = "grpc-stub", version.ref = "grpc" } +grpc-kotlin-stub = { group = "io.grpc", name = "grpc-kotlin-stub", version.ref = "grpcKotlin" } +protoc-gen-grpc-kotlin = { group = "io.grpc", name = "protoc-gen-grpc-kotlin", version.ref = "grpcKotlin" } +protobuf-kotlin-lite = { group = "com.google.protobuf", name = "protobuf-kotlin-lite", version.ref = "protobuf" } + tomcat-annotations = { group = "org.apache.tomcat", name = "annotations-api", version.ref = "tomcatAnnotations" } kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" } kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" } diff --git a/kuksa-java-sdk/build.gradle.kts b/kuksa-java-sdk/build.gradle.kts index 93e9f6a..7a56c5d 100644 --- a/kuksa-java-sdk/build.gradle.kts +++ b/kuksa-java-sdk/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ @file:Suppress("UnstableApiUsage") -import com.google.protobuf.gradle.id import org.eclipse.kuksa.version.SemanticVersion import org.eclipse.kuksa.version.VERSION_FILE_DEFAULT_PATH_KEY import org.jetbrains.dokka.gradle.DokkaTask @@ -95,11 +94,13 @@ dependencies { // needs to be api as long as we expose ProtoBuf specific objects api(libs.grpc.protobuf) + api(libs.protobuf.kotlin.lite) implementation(kotlin("reflect")) implementation(libs.grpc.okhttp) implementation(libs.grpc.stub) + implementation(libs.grpc.kotlin.stub) implementation(libs.tomcat.annotations) implementation(libs.kotlinx.coroutines.core) @@ -116,20 +117,29 @@ protobuf { artifact = libs.protobuf.protoc.get().toString() } plugins { - id("grpc") { + create("grpc") { artifact = libs.grpc.protoc.java.gen.get().toString() } - generateProtoTasks { - all().forEach { - it.builtins { - named("java") { - option("lite") - } + create("grpckt") { + artifact = libs.protoc.gen.grpc.kotlin.get().toString() + ":jdk8@jar" + } + } + generateProtoTasks { + all().forEach { + it.builtins { + named("java") { + option("lite") + } + create("kotlin") { + option("lite") + } + } + it.plugins { + create("grpc") { + option("lite") } - it.plugins { - create("grpc") { - option("lite") - } + create("grpckt") { + option("lite") } } } diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2.kt new file mode 100644 index 0000000..8ae694b --- /dev/null +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2.kt @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2 + +import io.grpc.ConnectivityState +import io.grpc.ManagedChannel +import kotlinx.coroutines.flow.Flow +import org.eclipse.kuksa.connectivity.authentication.JsonWebToken +import org.eclipse.kuksa.connectivity.databroker.DisconnectListener +import org.eclipse.kuksa.extension.TAG +import org.eclipse.kuksa.pattern.listener.MultiListener +import org.eclipse.kuksa.proto.v2.KuksaValV2 +import org.eclipse.kuksa.proto.v2.Types +import org.eclipse.kuksa.proto.v2.Types.Value +import java.util.logging.Logger +import kotlin.properties.Delegates + +class DataBrokerConnectionV2 internal constructor( + private val managedChannel: ManagedChannel, + private val dataBrokerTransporter: DataBrokerTransporterV2 = DataBrokerTransporterV2(managedChannel), +) { + private val logger = Logger.getLogger(TAG) + + /** + * Used to register and unregister multiple [DisconnectListener]. + */ + val disconnectListeners = MultiListener() + + /** + * A JsonWebToken can be provided to authenticate against the DataBroker. + */ + var jsonWebToken: JsonWebToken? by Delegates.observable(null) { _, _, newValue -> + dataBrokerTransporter.jsonWebToken = newValue + } + + init { + val state = managedChannel.getState(false) + managedChannel.notifyWhenStateChanged(state) { + val newState = managedChannel.getState(false) + logger.finer("DataBrokerConnection state changed: $newState") + if (newState != ConnectivityState.SHUTDOWN) { + managedChannel.shutdownNow() + } + + disconnectListeners.forEach { listener -> + listener.onDisconnect() + } + } + } + + /** + * Gets the latest value of a [signalId]. + * + * The server might respond with the following GRPC error codes: + * NOT_FOUND if the requested signal doesn't exist + * PERMISSION_DENIED if access is denied + */ + suspend fun fetchValue(signalId: Types.SignalID): KuksaValV2.GetValueResponse { + return dataBrokerTransporter.fetchValue(signalId) + } + + /** + * Gets the latest values of a set of [signalIds]. The returned list of data points has the same order as the list + * of the request. + * + * The server might respond with the following GRPC error codes: + * NOT_FOUND if any of the requested signals doesn't exist. + * PERMISSION_DENIED if access is denied for any of the requested signals. + */ + suspend fun fetchValues(signalIds: List): KuksaValV2.GetValuesResponse { + return dataBrokerTransporter.fetchValues(signalIds) + } + + /** + * Subscribe to a set of signals using i32 id parameters + * Returns (GRPC error code): + * NOT_FOUND if any of the signals are non-existent. + * PERMISSION_DENIED if access is denied for any of the signals. + */ + fun subscribeById( + signalIds: List, + ): Flow { + return dataBrokerTransporter.subscribeById(signalIds) + } + + /** + * Subscribe to a set of signals using string path parameters + * Returns (GRPC error code): + * NOT_FOUND if any of the signals are non-existent. + * PERMISSION_DENIED if access is denied for any of the signals. + * + * When subscribing the Broker shall immediately return the value for all + * subscribed entries. If no value is available when subscribing a DataPoint + * with value None shall be returned. + */ + fun subscribe( + signalPaths: List, + ): Flow { + return dataBrokerTransporter.subscribe(signalPaths) + } + + /** + * Actuates a single actuator with the specified [signalId]. + * + * The server might respond with the following GRPC error codes: + * NOT_FOUND if the actuator does not exist. + * PERMISSION_DENIED if access is denied for of the actuator. + * UNAVAILABLE if there is no provider currently providing the actuator + * INVALID_ARGUMENT + * - if the data type used in the request does not match the data type of the addressed signal + * - if the requested value is not accepted, e.g. if sending an unsupported enum value + */ + suspend fun actuate(signalId: Types.SignalID, value: Value): KuksaValV2.ActuateResponse { + return dataBrokerTransporter.actuate(signalId, value) + } + + /** + * Actuates simultaneously multiple actuators with the specified [signalIds]. + * If any error occurs, the entire operation will be aborted and no single actuator value will be forwarded to the + * provider. + * + * The server might respond with the following GRPC error codes: + * NOT_FOUND if any of the actuators are non-existent. + * PERMISSION_DENIED if access is denied for any of the actuators. + * UNAVAILABLE if there is no provider currently providing an actuator + * INVALID_ARGUMENT + * - if the data type used in the request does not match the data type of the addressed signal + * - if the requested value is not accepted, e.g. if sending an unsupported enum value + * + */ + suspend fun batchActuate(signalIds: List, value: Value): KuksaValV2.BatchActuateResponse { + return dataBrokerTransporter.batchActuate(signalIds, value) + } + + /** + * Lists metadata of signals matching the request. + * If any error occurs, the entire operation will be aborted and no single actuator value will be forwarded to the + * provider. + * + * The server might respond with the following GRPC error codes: + * NOT_FOUND if the specified root branch does not exist. + */ + suspend fun listMetadata( + root: String, + filter: String, + ): KuksaValV2.ListMetadataResponse { + return dataBrokerTransporter.listMetadata(root, filter) + } + + /** + * Publishes a signal value. Used for low frequency signals (e.g. attributes). + * + * The server might respond with the following GRPC error codes: + * NOT_FOUND if any of the signals are non-existent. + * PERMISSION_DENIED + * - if access is denied for any of the signals. + * - if the signal is already provided by another provider. + * INVALID_ARGUMENT + * - if the data type used in the request does not match the data type of the addressed signal + * - if the published value is not accepted e.g. if sending an unsupported enum value + */ + suspend fun publishValue( + signalId: Types.SignalID, + datapoint: Types.Datapoint, + ): KuksaValV2.PublishValueResponse { + return dataBrokerTransporter.publishValue(signalId, datapoint) + } + + /** + * Open a stream used to provide actuation and/or publishing values using + * a streaming interface. Used to provide actuators and to enable high frequency + * updates of values. + * + * The open stream is used for request / response type communication between the + * provider and server (where the initiator of a request can vary). + * Errors are communicated as messages in the stream. + */ + fun openProviderStream( + streamRequestFlow: Flow, + ): Flow { + return dataBrokerTransporter.openProviderStream(streamRequestFlow) + } + + /** + * Gets the server information. + */ + suspend fun fetchServerInfo(): KuksaValV2.GetServerInfoResponse { + return dataBrokerTransporter.fetchServerInfo() + } +} diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectorV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectorV2.kt new file mode 100644 index 0000000..dda66cc --- /dev/null +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectorV2.kt @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2 + +import io.grpc.ConnectivityState +import io.grpc.ManagedChannel +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.withContext +import org.eclipse.kuksa.connectivity.authentication.JsonWebToken +import org.eclipse.kuksa.connectivity.databroker.DataBrokerException +import org.eclipse.kuksa.extension.TAG +import org.eclipse.kuksa.model.TimeoutConfig +import java.util.logging.Logger + +/** + * The DataBrokerConnector is used to establish a successful connection to the DataBroker. The communication takes + * place inside the [managedChannel]. Use the [defaultDispatcher] for the coroutine scope. + */ +class DataBrokerConnectorV2 @JvmOverloads constructor( + private val managedChannel: ManagedChannel, + private val jsonWebToken: JsonWebToken? = null, + private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default, +) { + private val logger = Logger.getLogger(TAG) + + /** + * Configuration to be used during connection. + */ + var timeoutConfig = TimeoutConfig() + + /** + * Connects to the specified DataBroker. + * + * @throws DataBrokerException when connect() is called again while it is trying to connect (fail fast) resp. + * when no connection to the DataBroker can be established (e.g. after the in #timeoutConfig defined time). + */ + suspend fun connect(): DataBrokerConnectionV2 { + val connectivityState = managedChannel.getState(false) + if (connectivityState != ConnectivityState.IDLE) { + throw DataBrokerException("Connector is already trying to establish a connection") + } + + logger.finer("connect() called") + + return withContext(defaultDispatcher) { + val startTime = System.currentTimeMillis() + val timeoutMillis = timeoutConfig.timeUnit.toMillis(timeoutConfig.timeout) + var durationMillis = 0L + + @Suppress("MagicNumber") // self explanatory number + val delayMillis = 1000L + var state = managedChannel.getState(true) // is there no other way to connect? + while (state != ConnectivityState.READY && durationMillis < timeoutMillis - delayMillis) { + durationMillis = System.currentTimeMillis() - startTime + state = managedChannel.getState(false) + + delay(delayMillis) + } + + if (state == ConnectivityState.READY) { + return@withContext DataBrokerConnectionV2(managedChannel) + .apply { + jsonWebToken = this@DataBrokerConnectorV2.jsonWebToken + } + } else { + managedChannel.shutdownNow() + throw DataBrokerException("timeout") + } + } + } +} diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerTransporterV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerTransporterV2.kt new file mode 100644 index 0000000..a19be8e --- /dev/null +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerTransporterV2.kt @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2 + +import io.grpc.ConnectivityState +import io.grpc.ManagedChannel +import io.grpc.StatusException +import kotlinx.coroutines.flow.Flow +import org.eclipse.kuksa.connectivity.authentication.JsonWebToken +import org.eclipse.kuksa.connectivity.databroker.DataBrokerException +import org.eclipse.kuksa.connectivity.databroker.v2.extension.withAuthenticationInterceptor +import org.eclipse.kuksa.proto.v2.KuksaValV2 +import org.eclipse.kuksa.proto.v2.Types +import org.eclipse.kuksa.proto.v2.Types.Value +import org.eclipse.kuksa.proto.v2.VALGrpcKt +import org.eclipse.kuksa.proto.v2.actuateRequest +import org.eclipse.kuksa.proto.v2.batchActuateRequest +import org.eclipse.kuksa.proto.v2.getServerInfoRequest +import org.eclipse.kuksa.proto.v2.getValueRequest +import org.eclipse.kuksa.proto.v2.getValuesRequest +import org.eclipse.kuksa.proto.v2.listMetadataRequest +import org.eclipse.kuksa.proto.v2.publishValueRequest +import org.eclipse.kuksa.proto.v2.subscribeByIdRequest +import org.eclipse.kuksa.proto.v2.subscribeRequest + +/** + * Encapsulates the Protobuf-specific interactions with the DataBroker send over gRPC. + * The DataBrokerTransporter requires a [managedChannel] which is already connected to the corresponding DataBroker. + * + * @throws IllegalStateException in case the state of the [managedChannel] is not [ConnectivityState.READY] + */ +internal class DataBrokerTransporterV2( + private val managedChannel: ManagedChannel, +) { + + init { + val state = managedChannel.getState(false) + check(state == ConnectivityState.READY) { + "ManagedChannel needs to be connected to the target" + } + } + + /** + * A JsonWebToken can be provided to authenticate against the DataBroker. + */ + var jsonWebToken: JsonWebToken? = null + + private val coroutineStub: VALGrpcKt.VALCoroutineStub = VALGrpcKt.VALCoroutineStub(managedChannel) + + /** + * Gets the latest value of a [signalId]. + * + * The server might respond with the following GRPC error codes: + * NOT_FOUND if the requested signal doesn't exist + * PERMISSION_DENIED if access is denied + */ + suspend fun fetchValue(signalId: Types.SignalID): KuksaValV2.GetValueResponse { + val request = getValueRequest { + this.signalId = signalId + } + + return try { + coroutineStub + .withAuthenticationInterceptor(jsonWebToken) + .getValue(request) + } catch (e: StatusException) { + throw DataBrokerException(e.message, e) + } + } + + /** + * Gets the latest values of a set of [signalIds]. The returned list of data points has the same order as the list + * of the request. + * + * The server might respond with the following GRPC error codes: + * NOT_FOUND if any of the requested signals doesn't exist. + * PERMISSION_DENIED if access is denied for any of the requested signals. + */ + suspend fun fetchValues(signalIds: List): KuksaValV2.GetValuesResponse { + val request = getValuesRequest { + this.signalIds.addAll(signalIds) + } + + return try { + coroutineStub + .withAuthenticationInterceptor(jsonWebToken) + .getValues(request) + } catch (e: StatusException) { + throw DataBrokerException(e.message, e) + } + } + + /** + * Subscribe to a set of signals using i32 id parameters + * Returns (GRPC error code): + * NOT_FOUND if any of the signals are non-existent. + * PERMISSION_DENIED if access is denied for any of the signals. + */ + fun subscribeById( + signalIds: List, + ): Flow { + val request = subscribeByIdRequest { + this.signalIds.addAll(signalIds) + } + + return try { + coroutineStub + .withAuthenticationInterceptor(jsonWebToken) + .subscribeById(request) + } catch (e: StatusException) { + throw DataBrokerException(e.message, e) + } + } + + /** + * Subscribe to a set of signals using string path parameters + * Returns (GRPC error code): + * NOT_FOUND if any of the signals are non-existent. + * PERMISSION_DENIED if access is denied for any of the signals. + * + * When subscribing the Broker shall immediately return the value for all + * subscribed entries. If no value is available when subscribing a DataPoint + * with value None shall be returned. + */ + fun subscribe( + signalPaths: List, + ): Flow { + val request = subscribeRequest { + this.signalPaths.addAll(signalPaths) + } + + return try { + coroutineStub + .withAuthenticationInterceptor(jsonWebToken) + .subscribe(request) + } catch (e: StatusException) { + throw DataBrokerException(e.message, e) + } + } + + /** + * Actuates a single actuator with the specified [signalId]. + * + * The server might respond with the following GRPC error codes: + * NOT_FOUND if the actuator does not exist. + * PERMISSION_DENIED if access is denied for of the actuator. + * UNAVAILABLE if there is no provider currently providing the actuator + * INVALID_ARGUMENT + * - if the data type used in the request does not match the data type of the addressed signal + * - if the requested value is not accepted, e.g. if sending an unsupported enum value + */ + suspend fun actuate(signalId: Types.SignalID, value: Value): KuksaValV2.ActuateResponse { + val request = actuateRequest { + this.signalId = signalId + this.value = value + } + + return try { + coroutineStub + .withAuthenticationInterceptor(jsonWebToken) + .actuate(request) + } catch (e: StatusException) { + throw DataBrokerException(e.message, e) + } + } + + /** + * Actuates simultaneously multiple actuators with the specified [signalIds]. + * If any error occurs, the entire operation will be aborted and no single actuator value will be forwarded to the + * provider. + * + * The server might respond with the following GRPC error codes: + * NOT_FOUND if any of the actuators are non-existent. + * PERMISSION_DENIED if access is denied for any of the actuators. + * UNAVAILABLE if there is no provider currently providing an actuator + * INVALID_ARGUMENT + * - if the data type used in the request does not match the data type of the addressed signal + * - if the requested value is not accepted, e.g. if sending an unsupported enum value + * + */ + suspend fun batchActuate(signalIds: List, value: Value): KuksaValV2.BatchActuateResponse { + val request = batchActuateRequest { + signalIds.forEach { signalId -> + val actuateRequest = actuateRequest { + this.signalId = signalId + this.value = value + } + this.actuateRequests.add(actuateRequest) + } + } + + return try { + coroutineStub + .withAuthenticationInterceptor(jsonWebToken) + .batchActuate(request) + } catch (e: StatusException) { + throw DataBrokerException(e.message, e) + } + } + + /** + * Lists metadata of signals matching the request. + * If any error occurs, the entire operation will be aborted and no single actuator value will be forwarded to the + * provider. + * + * The server might respond with the following GRPC error codes: + * NOT_FOUND if the specified root branch does not exist. + */ + suspend fun listMetadata( + root: String, + filter: String, + ): KuksaValV2.ListMetadataResponse { + val request = listMetadataRequest { + this.root = root + this.filter = filter + } + + return try { + coroutineStub + .withAuthenticationInterceptor(jsonWebToken) + .listMetadata(request) + } catch (e: StatusException) { + throw DataBrokerException(e.message, e) + } + } + + /** + * Publishes a signal value. Used for low frequency signals (e.g. attributes). + * + * The server might respond with the following GRPC error codes: + * NOT_FOUND if any of the signals are non-existent. + * PERMISSION_DENIED + * - if access is denied for any of the signals. + * - if the signal is already provided by another provider. + * INVALID_ARGUMENT + * - if the data type used in the request does not match the data type of the addressed signal + * - if the published value is not accepted e.g. if sending an unsupported enum value + */ + suspend fun publishValue( + signalId: Types.SignalID, + datapoint: Types.Datapoint, + ): KuksaValV2.PublishValueResponse { + val request = publishValueRequest { + this.signalId = signalId + this.dataPoint = datapoint + } + + return try { + coroutineStub + .withAuthenticationInterceptor(jsonWebToken) + .publishValue(request) + } catch (e: StatusException) { + throw DataBrokerException(e.message, e) + } + } + + /** + * Open a stream used to provide actuation and/or publishing values using + * a streaming interface. Used to provide actuators and to enable high frequency + * updates of values. + * + * The open stream is used for request / response type communication between the + * provider and server (where the initiator of a request can vary). + * Errors are communicated as messages in the stream. + */ + fun openProviderStream( + streamRequestFlow: Flow, + ): Flow { + return try { + coroutineStub + .withAuthenticationInterceptor(jsonWebToken) + .openProviderStream(streamRequestFlow) + } catch (e: StatusException) { + throw DataBrokerException(e.message, e) + } + } + + /** + * Gets the server information. + */ + suspend fun fetchServerInfo(): KuksaValV2.GetServerInfoResponse { + val request = getServerInfoRequest { } + + return try { + coroutineStub + .withAuthenticationInterceptor(jsonWebToken) + .getServerInfo(request) + } catch (e: StatusException) { + throw DataBrokerException(e.message, e) + } + } +} diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extension/VALStubExtension.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extension/VALStubExtension.kt new file mode 100644 index 0000000..85cc3f0 --- /dev/null +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extension/VALStubExtension.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2.extension + +import com.google.common.net.HttpHeaders +import io.grpc.ClientInterceptor +import io.grpc.Metadata +import io.grpc.stub.MetadataUtils +import org.eclipse.kuksa.connectivity.authentication.JsonWebToken +import org.eclipse.kuksa.proto.v2.VALGrpcKt + +internal fun VALGrpcKt.VALCoroutineStub.withAuthenticationInterceptor( + jsonWebToken: JsonWebToken?, +): VALGrpcKt.VALCoroutineStub { + if (jsonWebToken == null) return this + + val authenticationInterceptor = clientInterceptor(jsonWebToken) + return withInterceptors(authenticationInterceptor) +} + +private fun clientInterceptor(jsonWebToken: JsonWebToken): ClientInterceptor? { + val authorizationHeader = Metadata.Key.of(HttpHeaders.AUTHORIZATION, Metadata.ASCII_STRING_MARSHALLER) + + val metadata = Metadata() + metadata.put(authorizationHeader, "${jsonWebToken.authScheme} ${jsonWebToken.token}") + + return MetadataUtils.newAttachHeadersInterceptor(metadata) +} diff --git a/kuksa-java-sdk/src/main/proto/kuksa/val/v2/types.proto b/kuksa-java-sdk/src/main/proto/kuksa/val/v2/types.proto new file mode 100644 index 0000000..7790a0f --- /dev/null +++ b/kuksa-java-sdk/src/main/proto/kuksa/val/v2/types.proto @@ -0,0 +1,229 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License 2.0 which is available at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +syntax = "proto3"; + +package kuksa.val.v2; +import "google/protobuf/timestamp.proto"; + +option go_package = "kuksa/val/v2"; +option java_package = "org.eclipse.kuksa.proto.v2"; + +// A Datapoint represents a timestamped value. +// The 'value' field can be explicitly 'None', meaning the Datapoint exists but no value is present. +message Datapoint { + google.protobuf.Timestamp timestamp = 1; // The timestamp of the datapoint. + Value value = 2; // The value associated with the timestamp. If no value is present, this field can be 'None'. +} + +message Value { + oneof typed_value { + string string = 11; + bool bool = 12; + sint32 int32 = 13; + sint64 int64 = 14; + uint32 uint32 = 15; + uint64 uint64 = 16; + float float = 17; + double double = 18; + StringArray string_array = 21; + BoolArray bool_array = 22; + Int32Array int32_array = 23; + Int64Array int64_array = 24; + Uint32Array uint32_array = 25; + Uint64Array uint64_array = 26; + FloatArray float_array = 27; + DoubleArray double_array = 28; + } +} + +message SignalID { + oneof signal { + // Numeric identifier to the signal + // As of today Databroker assigns arbitrary unique numbers to each registered signal + // at startup, meaning that identifiers may change after restarting Databroker. + // A mechanism for static identifiers may be introduced in the future. + int32 id = 1; + // Full VSS-style path to a specific signal, like "Vehicle.Speed" + // Wildcards and paths to branches are not supported. + // The given path must be known by the Databroker. + string path = 2; + } +} + +message Error { + ErrorCode code = 1; + string message = 2; +} + +enum ErrorCode { + OK = 0; + INVALID_ARGUMENT = 1; + NOT_FOUND = 2; + PERMISSION_DENIED = 3; +} + +message Metadata { + // ID field + int32 id = 10; // Unique identifier for the metadata entry + + // Data type + // The VSS data type of the entry (i.e. the value, min, max etc). + // + // NOTE: protobuf doesn't have int8, int16, uint8 or uint16 which means + // that these values must be serialized as int32 and uint32 respectively. + DataType data_type = 11; // [field: FIELD_METADATA_DATA_TYPE] + + // Entry type + EntryType entry_type = 12; // [field: FIELD_METADATA_ENTRY_TYPE] + + // Description + // Describes the meaning and content of the entry. + optional string description = 13; // [field: FIELD_METADATA_DESCRIPTION] + + // Comment [optional] + // A comment can be used to provide additional informal information + // on a entry. + optional string comment = 14; // [field: FIELD_METADATA_COMMENT] + + // Deprecation [optional] + // Whether this entry is deprecated. Can contain recommendations of what + // to use instead. + optional string deprecation = 15; // [field: FIELD_METADATA_DEPRECATION] + + // Unit [optional] + // The unit of measurement + optional string unit = 16; // [field: FIELD_METADATA_UNIT] + + // Value restrictions [optional] + // Restrict which values are allowed. + // Only restrictions matching the DataType {datatype} above are valid. + ValueRestriction value_restriction = 17; // [field: FIELD_METADATA_VALUE_RESTRICTION] +} + +// Value restriction +// +// One ValueRestriction{type} for each type, since +// they don't make sense unless the types match +// +message ValueRestriction { + oneof type { + ValueRestrictionString string = 21; + // For signed VSS integers + ValueRestrictionInt signed = 22; + // For unsigned VSS integers + ValueRestrictionUint unsigned = 23; + // For floating point VSS values (float and double) + ValueRestrictionFloat floating_point = 24; + } +} + +message ValueRestrictionInt { + optional sint64 min = 1; + optional sint64 max = 2; + repeated sint64 allowed_values = 3; +} + +message ValueRestrictionUint { + optional uint64 min = 1; + optional uint64 max = 2; + repeated uint64 allowed_values = 3; +} + +message ValueRestrictionFloat { + optional double min = 1; + optional double max = 2; + + // allowed for doubles/floats not recommended + repeated double allowed_values = 3; +} + +// min, max doesn't make much sense for a string +message ValueRestrictionString { + repeated string allowed_values = 1; +} + +// VSS Data type of a signal +// +// Protobuf doesn't support int8, int16, uint8 or uint16. +// These are mapped to int32 and uint32 respectively. +// +enum DataType { + DATA_TYPE_UNSPECIFIED = 0; + DATA_TYPE_STRING = 1; + DATA_TYPE_BOOLEAN = 2; + DATA_TYPE_INT8 = 3; + DATA_TYPE_INT16 = 4; + DATA_TYPE_INT32 = 5; + DATA_TYPE_INT64 = 6; + DATA_TYPE_UINT8 = 7; + DATA_TYPE_UINT16 = 8; + DATA_TYPE_UINT32 = 9; + DATA_TYPE_UINT64 = 10; + DATA_TYPE_FLOAT = 11; + DATA_TYPE_DOUBLE = 12; + DATA_TYPE_TIMESTAMP = 13; + DATA_TYPE_STRING_ARRAY = 20; + DATA_TYPE_BOOLEAN_ARRAY = 21; + DATA_TYPE_INT8_ARRAY = 22; + DATA_TYPE_INT16_ARRAY = 23; + DATA_TYPE_INT32_ARRAY = 24; + DATA_TYPE_INT64_ARRAY = 25; + DATA_TYPE_UINT8_ARRAY = 26; + DATA_TYPE_UINT16_ARRAY = 27; + DATA_TYPE_UINT32_ARRAY = 28; + DATA_TYPE_UINT64_ARRAY = 29; + DATA_TYPE_FLOAT_ARRAY = 30; + DATA_TYPE_DOUBLE_ARRAY = 31; + DATA_TYPE_TIMESTAMP_ARRAY = 32; +} + +// Entry type +enum EntryType { + ENTRY_TYPE_UNSPECIFIED = 0; + ENTRY_TYPE_ATTRIBUTE = 1; + ENTRY_TYPE_SENSOR = 2; + ENTRY_TYPE_ACTUATOR = 3; +} + +message StringArray { + repeated string values = 1; +} + +message BoolArray { + repeated bool values = 1; +} + +message Int32Array { + repeated sint32 values = 1; +} + +message Int64Array { + repeated sint64 values = 1; +} + +message Uint32Array { + repeated uint32 values = 1; +} + +message Uint64Array { + repeated uint64 values = 1; +} + +message FloatArray { + repeated float values = 1; +} + +message DoubleArray { + repeated double values = 1; +} diff --git a/kuksa-java-sdk/src/main/proto/kuksa/val/v2/val.proto b/kuksa-java-sdk/src/main/proto/kuksa/val/v2/val.proto new file mode 100644 index 0000000..ed2f1a2 --- /dev/null +++ b/kuksa-java-sdk/src/main/proto/kuksa/val/v2/val.proto @@ -0,0 +1,297 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License 2.0 which is available at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +syntax = "proto3"; + +package kuksa.val.v2; + +option go_package = "kuksa/val/v2"; +option java_package = "org.eclipse.kuksa.proto.v2"; +option java_outer_classname = "KuksaValV2"; + +import "kuksa/val/v2/types.proto"; + +service VAL { + // Get the latest value of a signal + // If the signal exist but does not have a valid value + // a DataPoint where value is None shall be returned. + // + // Returns (GRPC error code): + // NOT_FOUND if the requested signal doesn't exist + // UNAUTHENTICATED if no credentials provided or credentials has expired + // PERMISSION_DENIED if access is denied + // INVALID_ARGUMENT if the request is empty or provided path is too long + // - MAX_REQUEST_PATH_LENGTH: usize = 1000; + // + rpc GetValue(GetValueRequest) returns (GetValueResponse); + + // Get the latest values of a set of signals. + // The returned list of data points has the same order as the list of the request. + // If a requested signal has no value a DataPoint where value is None will be returned. + // + // Returns (GRPC error code): + // NOT_FOUND if any of the requested signals doesn't exist. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // PERMISSION_DENIED if access is denied for any of the requested signals. + // INVALID_ARGUMENT if the request is empty or provided path is too long + // - MAX_REQUEST_PATH_LENGTH: usize = 1000; + // + rpc GetValues(GetValuesRequest) returns (GetValuesResponse); + + // Subscribe to a set of signals using string path parameters + // Returns (GRPC error code): + // NOT_FOUND if any of the signals are non-existant. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // PERMISSION_DENIED if access is denied for any of the signals. + // INVALID_ARGUMENT if the request is empty or provided path is too long + // - MAX_REQUEST_PATH_LENGTH: usize = 1000; + // + // When subscribing, Databroker shall immediately return the value for all + // subscribed entries. + // If a value isn't available when subscribing to a it, it should return None + // + rpc Subscribe(SubscribeRequest) returns (stream SubscribeResponse); + + // Subscribe to a set of signals using i32 id parameters + // Returns (GRPC error code): + // NOT_FOUND if any of the signals are non-existant. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // PERMISSION_DENIED if access is denied for any of the signals. + // INVALID_ARGUMENT if the request is empty or provided path is too long + // + // When subscribing, Databroker shall immediately return the value for all + // subscribed entries. + // If a value isn't available when subscribing to a it, it should return None + // + rpc SubscribeById(SubscribeByIdRequest) returns (stream SubscribeByIdResponse); + + // Actuate a single actuator + // + // Returns (GRPC error code): + // NOT_FOUND if the actuator does not exist. + // PERMISSION_DENIED if access is denied for the actuator. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // UNAVAILABLE if there is no provider currently providing the actuator + // DATA_LOSS is there is a internal TransmissionFailure + // INVALID_ARGUMENT + // - if the provided path is not an actuator. + // - if the data type used in the request does not match + // the data type of the addressed signal + // - if the requested value is not accepted, + // e.g. if sending an unsupported enum value + // - if the provided value is out of the min/max range specified + // + rpc Actuate(ActuateRequest) returns (ActuateResponse); + + // Actuate simultaneously multiple actuators. + // If any error occurs, the entire operation will be aborted + // and no single actuator value will be forwarded to the provider. + // + // Returns (GRPC error code): + // NOT_FOUND if any of the actuators are non-existant. + // PERMISSION_DENIED if access is denied for any of the actuators. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // UNAVAILABLE if there is no provider currently providing an actuator + // DATA_LOSS is there is a internal TransmissionFailure + // INVALID_ARGUMENT + // - if any of the provided path is not an actuator. + // - if the data type used in the request does not match + // the data type of the addressed signal + // - if the requested value is not accepted, + // e.g. if sending an unsupported enum value + // - if any of the provided actuators values are out of the min/max range specified + // + rpc BatchActuate(BatchActuateRequest) returns (BatchActuateResponse); + + // List metadata of signals matching the request. + // + // Returns (GRPC error code): + // NOT_FOUND if the specified root branch does not exist. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // INVALID_ARGUMENT if the provided path or wildcard is wrong. + // + rpc ListMetadata(ListMetadataRequest) returns (ListMetadataResponse); + + // Publish a signal value. Used for low frequency signals (e.g. attributes). + // + // Returns (GRPC error code): + // NOT_FOUND if any of the signals are non-existant. + // PERMISSION_DENIED + // - if access is denied for any of the signals. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // INVALID_ARGUMENT + // - if the data type used in the request does not match + // the data type of the addressed signal + // - if the published value is not accepted, + // e.g. if sending an unsupported enum value + // - if the published value is out of the min/max range specified + // + rpc PublishValue(PublishValueRequest) returns (PublishValueResponse); + + // Open a stream used to provide actuation and/or publishing values using + // a streaming interface. Used to provide actuators and to enable high frequency + // updates of values. + // + // The open stream is used for request / response type communication between the + // provider and server (where the initiator of a request can vary). + // + // Errors: + // - Provider sends ProvideActuationRequest -> Databroker returns ProvideActuationResponse + // Returns (GRPC error code) and closes the stream call (strict case). + // NOT_FOUND if any of the signals are non-existant. + // PERMISSION_DENIED if access is denied for any of the signals. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // ALREADY_EXISTS if a provider already claimed the ownership of an actuator + // + // - Provider sends PublishValuesRequest -> Databroker returns PublishValuesResponse + // GRPC errors are returned as messages in the stream + // response with the signal id `map status = 2;` (permissive case) + // NOT_FOUND if a signal is non-existant. + // PERMISSION_DENIED + // - if access is denied for a signal. + // INVALID_ARGUMENT + // - if the data type used in the request does not match + // the data type of the addressed signal + // - if the published value is not accepted, + // e.g. if sending an unsupported enum value + // - if the published value is out of the min/max range specified + // + // - Provider returns BatchActuateStreamResponse <- Databroker sends BatchActuateStreamRequest + // No error definition, a BatchActuateStreamResponse is expected from provider. + // + rpc OpenProviderStream(stream OpenProviderStreamRequest) returns (stream OpenProviderStreamResponse); + + // Get server information + rpc GetServerInfo(GetServerInfoRequest) returns (GetServerInfoResponse); +} + +message GetValueRequest { + SignalID signal_id = 1; +} + +message GetValueResponse { + Datapoint data_point = 1; +} + +message GetValuesRequest { + repeated SignalID signal_ids = 1; +} + +message GetValuesResponse { + repeated Datapoint data_points = 1; +} + +message SubscribeRequest { + repeated string signal_paths = 1; +} + +message SubscribeResponse { + map entries = 1; +} + +message SubscribeByIdRequest { + repeated int32 signal_ids = 1; +} + +message SubscribeByIdResponse { + map entries = 1; +} + +message ActuateRequest { + SignalID signal_id = 1; + Value value = 2; +} + +message ActuateResponse { +} + +message BatchActuateRequest { + repeated ActuateRequest actuate_requests = 1; +} + +message BatchActuateResponse { +} + +message ListMetadataRequest { + string root = 1; + string filter = 2; +} + +message ListMetadataResponse { + repeated Metadata metadata = 1; +} + +message PublishValueRequest { + SignalID signal_id = 1; + Datapoint data_point = 2; +} + +message PublishValueResponse { +} + +message PublishValuesRequest { + int32 request_id = 1; /// Unique request id for the stream that can be used to identify the response. + map datapoints = 2; +} + +message PublishValuesResponse { + int32 request_id = 1; + map status = 2; +} + +message ProvideActuationRequest { + repeated SignalID actuator_identifiers = 1; +} + +message ProvideActuationResponse { +} + +message BatchActuateStreamRequest { + repeated ActuateRequest actuate_requests = 1; +} + +message BatchActuateStreamResponse { +} + +message OpenProviderStreamRequest { + oneof action { + // Inform server of an actuator this provider provides. + ProvideActuationRequest provide_actuation_request = 1; + // Publish a value. + PublishValuesRequest publish_values_request = 2; + // Sent to acknowledge the acceptance of a batch actuate + // request. + BatchActuateStreamResponse batch_actuate_stream_response = 3; + } +} + +message OpenProviderStreamResponse { + oneof action { + // Response to a provide actuator request. + ProvideActuationResponse provide_actuation_response = 1; + // Acknowledgement that a published value was received. + PublishValuesResponse publish_values_response = 2; + // Send a batch actuate request to a provider. + BatchActuateStreamRequest batch_actuate_stream_request = 3; + } +} + +message GetServerInfoRequest { + // Nothing yet +} + +message GetServerInfoResponse { + string name = 1; + string version = 2; + string commit_hash = 3; +} From c9e611ba6e80339f644ca09206997fe0a7288894 Mon Sep 17 00:00:00 2001 From: Andre Weber Date: Thu, 9 Jan 2025 11:06:19 +0100 Subject: [PATCH 4/9] chore: Add *Request Model for each Operation --- .../databroker/v2/DataBrokerConnectionV2.kt | 46 ++++++++++--------- .../databroker/v2/request/ActuateRequestV2.kt | 28 +++++++++++ .../v2/request/BatchActuateRequestV2.kt | 29 ++++++++++++ .../v2/request/FetchValueRequestV2.kt | 27 +++++++++++ .../v2/request/FetchValuesRequestV2.kt | 28 +++++++++++ .../v2/request/ListMetadataRequestV2.kt | 26 +++++++++++ .../v2/request/PublishValueRequestV2.kt | 28 +++++++++++ .../v2/request/SubscribeByIdRequestV2.kt | 26 +++++++++++ .../v2/request/SubscribeRequestV2.kt | 25 ++++++++++ 9 files changed, 241 insertions(+), 22 deletions(-) create mode 100644 kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/ActuateRequestV2.kt create mode 100644 kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/BatchActuateRequestV2.kt create mode 100644 kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/FetchValueRequestV2.kt create mode 100644 kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/FetchValuesRequestV2.kt create mode 100644 kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/ListMetadataRequestV2.kt create mode 100644 kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/PublishValueRequestV2.kt create mode 100644 kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/SubscribeByIdRequestV2.kt create mode 100644 kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/SubscribeRequestV2.kt diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2.kt index 8ae694b..97e6565 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2.kt @@ -24,11 +24,17 @@ import io.grpc.ManagedChannel import kotlinx.coroutines.flow.Flow import org.eclipse.kuksa.connectivity.authentication.JsonWebToken import org.eclipse.kuksa.connectivity.databroker.DisconnectListener +import org.eclipse.kuksa.connectivity.databroker.v2.request.ActuateRequestV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.BatchActuateRequestV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.FetchValueRequestV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.FetchValuesRequestV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.ListMetadataRequestV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.PublishValueRequestV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.SubscribeByIdRequestV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.SubscribeRequestV2 import org.eclipse.kuksa.extension.TAG import org.eclipse.kuksa.pattern.listener.MultiListener import org.eclipse.kuksa.proto.v2.KuksaValV2 -import org.eclipse.kuksa.proto.v2.Types -import org.eclipse.kuksa.proto.v2.Types.Value import java.util.logging.Logger import kotlin.properties.Delegates @@ -72,8 +78,8 @@ class DataBrokerConnectionV2 internal constructor( * NOT_FOUND if the requested signal doesn't exist * PERMISSION_DENIED if access is denied */ - suspend fun fetchValue(signalId: Types.SignalID): KuksaValV2.GetValueResponse { - return dataBrokerTransporter.fetchValue(signalId) + suspend fun fetchValue(request: FetchValueRequestV2): KuksaValV2.GetValueResponse { + return dataBrokerTransporter.fetchValue(request.signalId) } /** @@ -84,8 +90,8 @@ class DataBrokerConnectionV2 internal constructor( * NOT_FOUND if any of the requested signals doesn't exist. * PERMISSION_DENIED if access is denied for any of the requested signals. */ - suspend fun fetchValues(signalIds: List): KuksaValV2.GetValuesResponse { - return dataBrokerTransporter.fetchValues(signalIds) + suspend fun fetchValues(request: FetchValuesRequestV2): KuksaValV2.GetValuesResponse { + return dataBrokerTransporter.fetchValues(request.signalIds) } /** @@ -95,9 +101,9 @@ class DataBrokerConnectionV2 internal constructor( * PERMISSION_DENIED if access is denied for any of the signals. */ fun subscribeById( - signalIds: List, + request: SubscribeByIdRequestV2, ): Flow { - return dataBrokerTransporter.subscribeById(signalIds) + return dataBrokerTransporter.subscribeById(request.signalIds) } /** @@ -111,9 +117,9 @@ class DataBrokerConnectionV2 internal constructor( * with value None shall be returned. */ fun subscribe( - signalPaths: List, + request: SubscribeRequestV2, ): Flow { - return dataBrokerTransporter.subscribe(signalPaths) + return dataBrokerTransporter.subscribe(request.signalPaths) } /** @@ -127,8 +133,8 @@ class DataBrokerConnectionV2 internal constructor( * - if the data type used in the request does not match the data type of the addressed signal * - if the requested value is not accepted, e.g. if sending an unsupported enum value */ - suspend fun actuate(signalId: Types.SignalID, value: Value): KuksaValV2.ActuateResponse { - return dataBrokerTransporter.actuate(signalId, value) + suspend fun actuate(request: ActuateRequestV2): KuksaValV2.ActuateResponse { + return dataBrokerTransporter.actuate(request.signalId, request.value) } /** @@ -145,8 +151,8 @@ class DataBrokerConnectionV2 internal constructor( * - if the requested value is not accepted, e.g. if sending an unsupported enum value * */ - suspend fun batchActuate(signalIds: List, value: Value): KuksaValV2.BatchActuateResponse { - return dataBrokerTransporter.batchActuate(signalIds, value) + suspend fun batchActuate(request: BatchActuateRequestV2): KuksaValV2.BatchActuateResponse { + return dataBrokerTransporter.batchActuate(request.signalIds, request.value) } /** @@ -157,11 +163,8 @@ class DataBrokerConnectionV2 internal constructor( * The server might respond with the following GRPC error codes: * NOT_FOUND if the specified root branch does not exist. */ - suspend fun listMetadata( - root: String, - filter: String, - ): KuksaValV2.ListMetadataResponse { - return dataBrokerTransporter.listMetadata(root, filter) + suspend fun listMetadata(request: ListMetadataRequestV2): KuksaValV2.ListMetadataResponse { + return dataBrokerTransporter.listMetadata(request.root, request.filter) } /** @@ -177,10 +180,9 @@ class DataBrokerConnectionV2 internal constructor( * - if the published value is not accepted e.g. if sending an unsupported enum value */ suspend fun publishValue( - signalId: Types.SignalID, - datapoint: Types.Datapoint, + request: PublishValueRequestV2, ): KuksaValV2.PublishValueResponse { - return dataBrokerTransporter.publishValue(signalId, datapoint) + return dataBrokerTransporter.publishValue(request.signalId, request.datapoint) } /** diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/ActuateRequestV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/ActuateRequestV2.kt new file mode 100644 index 0000000..01364e4 --- /dev/null +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/ActuateRequestV2.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2.request + +import org.eclipse.kuksa.proto.v2.Types +import org.eclipse.kuksa.proto.v2.Types.Value + +/** + * Used for actuate requests with [org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerConnectionV2.actuate]. + */ +class ActuateRequestV2(val signalId: Types.SignalID, val value: Value) diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/BatchActuateRequestV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/BatchActuateRequestV2.kt new file mode 100644 index 0000000..ca144b3 --- /dev/null +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/BatchActuateRequestV2.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2.request + +import org.eclipse.kuksa.proto.v2.Types +import org.eclipse.kuksa.proto.v2.Types.Value + +/** + * Used for batch actuate requests with + * [org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerConnectionV2.batchActuate]. + */ +class BatchActuateRequestV2(val signalIds: List, val value: Value) diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/FetchValueRequestV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/FetchValueRequestV2.kt new file mode 100644 index 0000000..fa18431 --- /dev/null +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/FetchValueRequestV2.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2.request + +import org.eclipse.kuksa.proto.v2.Types + +/** + * Used for fetch value requests with [org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerConnectionV2.fetchValue]. + */ +class FetchValueRequestV2(val signalId: Types.SignalID) diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/FetchValuesRequestV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/FetchValuesRequestV2.kt new file mode 100644 index 0000000..3b3daa5 --- /dev/null +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/FetchValuesRequestV2.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2.request + +import org.eclipse.kuksa.proto.v2.Types + +/** + * Used for fetch values requests with + * [org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerConnectionV2.fetchValues]. + */ +class FetchValuesRequestV2(val signalIds: List) diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/ListMetadataRequestV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/ListMetadataRequestV2.kt new file mode 100644 index 0000000..12a0533 --- /dev/null +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/ListMetadataRequestV2.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2.request + +/** + * Used for list metadata requests with + * [org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerConnectionV2.listMetadata]. + */ +class ListMetadataRequestV2(val root: String, val filter: String) diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/PublishValueRequestV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/PublishValueRequestV2.kt new file mode 100644 index 0000000..e2316ec --- /dev/null +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/PublishValueRequestV2.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2.request + +import org.eclipse.kuksa.proto.v2.Types + +/** + * Used for publish value requests with + * [org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerConnectionV2.publishValue]. + */ +class PublishValueRequestV2(val signalId: Types.SignalID, val datapoint: Types.Datapoint) diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/SubscribeByIdRequestV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/SubscribeByIdRequestV2.kt new file mode 100644 index 0000000..baecf06 --- /dev/null +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/SubscribeByIdRequestV2.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2.request + +/** + * Used for subscribe by id requests with + * [org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerConnectionV2.subscribeById]. + */ +class SubscribeByIdRequestV2(val signalIds: List) diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/SubscribeRequestV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/SubscribeRequestV2.kt new file mode 100644 index 0000000..e0e82f2 --- /dev/null +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/request/SubscribeRequestV2.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2.request + +/** + * Used for subscribe requests with [org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerConnectionV2.subscribe]. + */ +class SubscribeRequestV2(val signalPaths: List) From 70c43f1cad8b830e2fd273ccc9fe9a7987cc04d6 Mon Sep 17 00:00:00 2001 From: Andre Weber Date: Thu, 9 Jan 2025 09:49:22 +0100 Subject: [PATCH 5/9] docs: Add Samples --- samples/.gitignore | 1 + samples/build.gradle.kts | 23 +++ .../src/main/java/com/example/samples/Main.kt | 131 ++++++++++++++++++ settings.gradle.kts | 1 + 4 files changed, 156 insertions(+) create mode 100644 samples/.gitignore create mode 100644 samples/build.gradle.kts create mode 100644 samples/src/main/java/com/example/samples/Main.kt diff --git a/samples/.gitignore b/samples/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/samples/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/samples/build.gradle.kts b/samples/build.gradle.kts new file mode 100644 index 0000000..64d0b5d --- /dev/null +++ b/samples/build.gradle.kts @@ -0,0 +1,23 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + id("application") + kotlin("jvm") +} + +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + +kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_11) + } +} + +dependencies { + implementation(project(":kuksa-java-sdk")) + + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") +} diff --git a/samples/src/main/java/com/example/samples/Main.kt b/samples/src/main/java/com/example/samples/Main.kt new file mode 100644 index 0000000..a768167 --- /dev/null +++ b/samples/src/main/java/com/example/samples/Main.kt @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package com.example.samples + +import io.grpc.ManagedChannelBuilder +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch +import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnector +import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssPathListener +import org.eclipse.kuksa.connectivity.databroker.v1.request.FetchRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.SubscribeRequest +import org.eclipse.kuksa.connectivity.databroker.v1.request.UpdateRequest +import org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerConnectorV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.FetchValueRequestV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.PublishValueRequestV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.SubscribeRequestV2 +import org.eclipse.kuksa.proto.v1.KuksaValV1 +import org.eclipse.kuksa.proto.v1.Types.Datapoint +import org.eclipse.kuksa.proto.v2.Types +import org.eclipse.kuksa.proto.v2.Types.SignalID +import org.eclipse.kuksa.vsscore.annotation.VssModelGenerator + +@VssModelGenerator +class Main + +suspend fun main() { + useKuksaValV1() + useKuksaValV2() +} + +@Suppress("MagicNumber") +private suspend fun useKuksaValV1() { + val managedChannel = ManagedChannelBuilder.forAddress("localhost", 55556) + .usePlaintext() + .build() + val dataBrokerConnector = DataBrokerConnector(managedChannel) + + coroutineScope { + launch { + val dataBrokerConnection = dataBrokerConnector.connect() + + println("Using protocol kuksa.val.v1") + println("Setting Vehicle.Speed in Databroker to 80") + val vssPath = "Vehicle.Speed" + + val dataPoint = Datapoint.newBuilder().setFloat(80.0F).build() + val updateRequest = UpdateRequest(vssPath, dataPoint) + dataBrokerConnection.update(updateRequest) + + println("Reading Vehicle.Speed from Databroker") + val fetchRequest = FetchRequest(vssPath) + val response = dataBrokerConnection.fetch(fetchRequest) + println("GetResponse: " + response) + + println("Observe Vehicle.Speed") + val subscribeRequest = SubscribeRequest("Vehicle.Speed") + dataBrokerConnection.subscribe( + subscribeRequest, + object : VssPathListener { + override fun onEntryChanged(entryUpdates: List) { + entryUpdates.forEach { entryUpdate -> + val vehicleSpeedValue = entryUpdate.entry.value.float + // handle change + println("newSpeed(v1): $vehicleSpeedValue") + } + } + + override fun onError(throwable: Throwable) { + // handle error + } + }, + ) + } + } +} + +@Suppress("MagicNumber") +private suspend fun useKuksaValV2() { + val managedChannel = ManagedChannelBuilder.forAddress("localhost", 55556) + .usePlaintext() + .build() + val dataBrokerConnector = DataBrokerConnectorV2(managedChannel) + + coroutineScope { + launch { + val dataBrokerConnection = dataBrokerConnector.connect() + + println("Using protocol kuksa.val.v2") + println("Setting Vehicle.Speed in Databroker to 60") + + val signalId = SignalID.newBuilder().setPath("Vehicle.Speed").build() + val speedValue = Types.Value.newBuilder().setFloat(60.0F).build() + val datapoint = Types.Datapoint.newBuilder().setValue(speedValue).build() + + val publishValueRequest = PublishValueRequestV2(signalId, datapoint) + dataBrokerConnection.publishValue(publishValueRequest) + + println("Reading Vehicle.Speed from Databroker") + val fetchValueRequest = FetchValueRequestV2(signalId) + val fetchResponse = dataBrokerConnection.fetchValue(fetchValueRequest) + println(fetchResponse) + + println("Observe Vehicle.Speed") + val signalPaths = listOf("Vehicle.Speed") + val subscribeRequest = SubscribeRequestV2(signalPaths) + val responseFlow = dataBrokerConnection.subscribe(subscribeRequest) + responseFlow.collect { response -> + val vehicleSpeedValue = response.entriesMap["Vehicle.Speed"]?.value?.float + // handle change + println("newSpeed(v2): $vehicleSpeedValue") + } + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index dcdab87..23f8427 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -47,3 +47,4 @@ rootProject.name = "kuksa-java-sdk" include(":kuksa-java-sdk") include(":vss-core") include(":test-core") +include(":samples") From 6e08ca0639e39f731742eda3c9ecc118c28b76e2 Mon Sep 17 00:00:00 2001 From: Andre Weber Date: Thu, 9 Jan 2025 10:42:01 +0100 Subject: [PATCH 6/9] chore: Use CoroutineStub in kuksa.val.v1 --- .../databroker/v1/DataBrokerConnection.kt | 1 - .../databroker/v1/DataBrokerTransporter.kt | 85 +++++++++---------- .../v1/extension/VALStubExtension.kt | 10 +++ 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnection.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnection.kt index 6b59a00..e75eead 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnection.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnection.kt @@ -61,7 +61,6 @@ class DataBrokerConnection internal constructor( private val dispatcher: CoroutineDispatcher = Dispatchers.Default, private val dataBrokerTransporter: DataBrokerTransporter = DataBrokerTransporter( managedChannel, - dispatcher, ), private val dataBrokerSubscriber: DataBrokerSubscriber = DataBrokerSubscriber(dataBrokerTransporter), ) { diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerTransporter.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerTransporter.kt index 06966a2..4a468f6 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerTransporter.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerTransporter.kt @@ -22,11 +22,8 @@ package org.eclipse.kuksa.connectivity.databroker.v1 import io.grpc.ConnectivityState import io.grpc.Context import io.grpc.ManagedChannel -import io.grpc.StatusRuntimeException +import io.grpc.StatusException import io.grpc.stub.StreamObserver -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext import org.eclipse.kuksa.connectivity.authentication.JsonWebToken import org.eclipse.kuksa.connectivity.databroker.DataBrokerException import org.eclipse.kuksa.connectivity.databroker.v1.extension.withAuthenticationInterceptor @@ -38,6 +35,7 @@ import org.eclipse.kuksa.proto.v1.KuksaValV1.SubscribeResponse import org.eclipse.kuksa.proto.v1.Types import org.eclipse.kuksa.proto.v1.Types.Field import org.eclipse.kuksa.proto.v1.VALGrpc +import org.eclipse.kuksa.proto.v1.VALGrpcKt import java.util.logging.Logger /** @@ -50,7 +48,6 @@ import java.util.logging.Logger */ internal class DataBrokerTransporter( private val managedChannel: ManagedChannel, - private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default, ) { private val logger = Logger.getLogger(TAG) @@ -62,6 +59,9 @@ internal class DataBrokerTransporter( } } + private val coroutineStub = VALGrpcKt.VALCoroutineStub(managedChannel) + private val asyncStub = VALGrpc.newStub(managedChannel) + /** * A JsonWebToken can be provided to authenticate against the DataBroker. */ @@ -76,23 +76,20 @@ internal class DataBrokerTransporter( vssPath: String, fields: Collection, ): KuksaValV1.GetResponse { - return withContext(defaultDispatcher) { - val blockingStub = VALGrpc.newBlockingStub(managedChannel) - val entryRequest = KuksaValV1.EntryRequest.newBuilder() - .setPath(vssPath) - .addAllFields(fields.toSet()) - .build() - val request = KuksaValV1.GetRequest.newBuilder() - .addEntries(entryRequest) - .build() + val entryRequest = KuksaValV1.EntryRequest.newBuilder() + .setPath(vssPath) + .addAllFields(fields.toSet()) + .build() + val request = KuksaValV1.GetRequest.newBuilder() + .addEntries(entryRequest) + .build() - return@withContext try { - blockingStub - .withAuthenticationInterceptor(jsonWebToken) - .get(request) - } catch (e: StatusRuntimeException) { - throw DataBrokerException(e.message, e) - } + return try { + coroutineStub + .withAuthenticationInterceptor(jsonWebToken) + .get(request) + } catch (e: StatusException) { + throw DataBrokerException(e.message, e) } } @@ -107,32 +104,28 @@ internal class DataBrokerTransporter( updatedDatapoint: Types.Datapoint, fields: Collection, ): KuksaValV1.SetResponse { - return withContext(defaultDispatcher) { - val blockingStub = VALGrpc.newBlockingStub(managedChannel) - - val entryUpdates = fields.map { field -> - val dataEntry = Types.DataEntry.newBuilder() - .setPath(vssPath) - .applyDatapoint(updatedDatapoint, field) - .build() - - KuksaValV1.EntryUpdate.newBuilder() - .setEntry(dataEntry) - .addFields(field) - .build() - } + val entryUpdates = fields.map { field -> + val dataEntry = Types.DataEntry.newBuilder() + .setPath(vssPath) + .applyDatapoint(updatedDatapoint, field) + .build() - val request = KuksaValV1.SetRequest.newBuilder() - .addAllUpdates(entryUpdates) + KuksaValV1.EntryUpdate.newBuilder() + .setEntry(dataEntry) + .addFields(field) .build() + } - return@withContext try { - blockingStub - .withAuthenticationInterceptor(jsonWebToken) - .set(request) - } catch (e: StatusRuntimeException) { - throw DataBrokerException(e.message, e) - } + val request = KuksaValV1.SetRequest.newBuilder() + .addAllUpdates(entryUpdates) + .build() + + return try { + coroutineStub + .withAuthenticationInterceptor(jsonWebToken) + .set(request) + } catch (e: StatusException) { + throw DataBrokerException(e.message, e) } } @@ -147,8 +140,6 @@ internal class DataBrokerTransporter( vssPath: String, field: Field, ): DataBrokerSubscription { - val asyncStub = VALGrpc.newStub(managedChannel) - val subscribeEntry = KuksaValV1.SubscribeEntry.newBuilder() .setPath(vssPath) .addFields(field) @@ -189,7 +180,7 @@ internal class DataBrokerTransporter( asyncStub .withAuthenticationInterceptor(jsonWebToken) .subscribe(request, streamObserver) - } catch (e: StatusRuntimeException) { + } catch (e: StatusException) { throw DataBrokerException(e.message, e) } } diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/extension/VALStubExtension.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/extension/VALStubExtension.kt index 2d941fa..f5783ed 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/extension/VALStubExtension.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/extension/VALStubExtension.kt @@ -26,6 +26,7 @@ import io.grpc.stub.MetadataUtils import org.eclipse.kuksa.connectivity.authentication.JsonWebToken import org.eclipse.kuksa.proto.v1.VALGrpc.VALBlockingStub import org.eclipse.kuksa.proto.v1.VALGrpc.VALStub +import org.eclipse.kuksa.proto.v1.VALGrpcKt.VALCoroutineStub internal fun VALBlockingStub.withAuthenticationInterceptor(jsonWebToken: JsonWebToken?): VALBlockingStub { if (jsonWebToken == null) return this @@ -41,6 +42,15 @@ internal fun VALStub.withAuthenticationInterceptor(jsonWebToken: JsonWebToken?): return withInterceptors(authenticationInterceptor) } +internal fun VALCoroutineStub.withAuthenticationInterceptor( + jsonWebToken: JsonWebToken?, +): VALCoroutineStub { + if (jsonWebToken == null) return this + + val authenticationInterceptor = clientInterceptor(jsonWebToken) + return withInterceptors(authenticationInterceptor) +} + private fun clientInterceptor(jsonWebToken: JsonWebToken): ClientInterceptor? { val authorizationHeader = Metadata.Key.of(HttpHeaders.AUTHORIZATION, Metadata.ASCII_STRING_MARSHALLER) From 48880b7ccf17244765771332e08c3a4ea6118276 Mon Sep 17 00:00:00 2001 From: Andre Weber Date: Thu, 9 Jan 2025 11:14:30 +0100 Subject: [PATCH 7/9] test: Move Tests into v1 folder --- .../{ => v1}/DataBrokerConnectionTest.kt | 8 ++++---- .../{ => v1}/DataBrokerConnectorSecureTest.kt | 6 ++++-- .../{ => v1}/DataBrokerConnectorTest.kt | 7 +++++-- .../{ => v1}/DataBrokerTransporterTest.kt | 9 +++++---- .../DataBrokerConnectorAuthenticationTest.kt | 7 ++++--- .../extensions/DataBrokerTransporterExtensions.kt | 4 ++-- .../provider}/DataBrokerConnectorProvider.kt | 11 ++++++++--- .../subscription/DataBrokerSubscriberTest.kt | 15 +++++++-------- .../authentication => mocking}/JwtType.kt | 4 ++-- 9 files changed, 41 insertions(+), 30 deletions(-) rename kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/DataBrokerConnectionTest.kt (98%) rename kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/DataBrokerConnectorSecureTest.kt (91%) rename kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/DataBrokerConnectorTest.kt (90%) rename kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/DataBrokerTransporterTest.kt (95%) rename kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/{ => databroker/v1}/authentication/DataBrokerConnectorAuthenticationTest.kt (97%) rename kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/{ => connectivity/databroker/v1}/extensions/DataBrokerTransporterExtensions.kt (94%) rename kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1/provider}/DataBrokerConnectorProvider.kt (89%) rename kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/{ => v1}/subscription/DataBrokerSubscriberTest.kt (96%) rename kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/{connectivity/authentication => mocking}/JwtType.kt (91%) diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectionTest.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnectionTest.kt similarity index 98% rename from kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectionTest.kt rename to kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnectionTest.kt index 58762f7..118e306 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectionTest.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnectionTest.kt @@ -17,7 +17,7 @@ * */ -package org.eclipse.kuksa.connectivity.databroker +package org.eclipse.kuksa.connectivity.databroker.v1 import io.grpc.ConnectivityState import io.grpc.ManagedChannel @@ -28,17 +28,17 @@ import io.kotest.matchers.shouldNotBe import io.mockk.every import io.mockk.mockk import io.mockk.verify +import org.eclipse.kuksa.connectivity.databroker.DisconnectListener import org.eclipse.kuksa.connectivity.databroker.docker.DataBrokerDockerContainer import org.eclipse.kuksa.connectivity.databroker.docker.InsecureDataBrokerDockerContainer -import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnection -import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerTransporter +import org.eclipse.kuksa.connectivity.databroker.v1.extensions.updateRandomFloatValue +import org.eclipse.kuksa.connectivity.databroker.v1.provider.DataBrokerConnectorProvider import org.eclipse.kuksa.connectivity.databroker.v1.request.FetchRequest import org.eclipse.kuksa.connectivity.databroker.v1.request.SubscribeRequest import org.eclipse.kuksa.connectivity.databroker.v1.request.UpdateRequest import org.eclipse.kuksa.connectivity.databroker.v1.request.VssNodeFetchRequest import org.eclipse.kuksa.connectivity.databroker.v1.request.VssNodeSubscribeRequest import org.eclipse.kuksa.connectivity.databroker.v1.request.VssNodeUpdateRequest -import org.eclipse.kuksa.extensions.updateRandomFloatValue import org.eclipse.kuksa.mocking.FriendlyVssNodeListener import org.eclipse.kuksa.mocking.FriendlyVssPathListener import org.eclipse.kuksa.proto.v1.Types diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectorSecureTest.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnectorSecureTest.kt similarity index 91% rename from kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectorSecureTest.kt rename to kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnectorSecureTest.kt index 02b6019..ea282ef 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectorSecureTest.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnectorSecureTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,15 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker +package org.eclipse.kuksa.connectivity.databroker.v1 import io.kotest.core.spec.style.BehaviorSpec import org.eclipse.kuksa.connectivity.databroker.docker.DataBrokerDockerContainer import org.eclipse.kuksa.connectivity.databroker.docker.SecureDataBrokerDockerContainer +import org.eclipse.kuksa.connectivity.databroker.v1.provider.DataBrokerConnectorProvider import org.eclipse.kuksa.test.TestResourceFile import org.eclipse.kuksa.test.kotest.Integration import org.eclipse.kuksa.test.kotest.Secure diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectorTest.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnectorTest.kt similarity index 90% rename from kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectorTest.kt rename to kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnectorTest.kt index 82ce9e5..d42c4a7 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectorTest.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerConnectorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,15 +14,18 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker +package org.eclipse.kuksa.connectivity.databroker.v1 import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldNotBe +import org.eclipse.kuksa.connectivity.databroker.DataBrokerException import org.eclipse.kuksa.connectivity.databroker.docker.DataBrokerDockerContainer import org.eclipse.kuksa.connectivity.databroker.docker.InsecureDataBrokerDockerContainer +import org.eclipse.kuksa.connectivity.databroker.v1.provider.DataBrokerConnectorProvider import org.eclipse.kuksa.test.kotest.Insecure import org.eclipse.kuksa.test.kotest.InsecureDataBroker import org.eclipse.kuksa.test.kotest.Integration diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerTransporterTest.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerTransporterTest.kt similarity index 95% rename from kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerTransporterTest.kt rename to kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerTransporterTest.kt index fa546ac..92fc61e 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerTransporterTest.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/DataBrokerTransporterTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,10 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker +package org.eclipse.kuksa.connectivity.databroker.v1 import io.grpc.ManagedChannelBuilder import io.kotest.assertions.nondeterministic.eventually @@ -28,9 +29,9 @@ import io.mockk.mockk import io.mockk.verify import org.eclipse.kuksa.connectivity.databroker.docker.DataBrokerDockerContainer import org.eclipse.kuksa.connectivity.databroker.docker.InsecureDataBrokerDockerContainer -import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerTransporter +import org.eclipse.kuksa.connectivity.databroker.v1.extensions.updateRandomFloatValue import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssPathListener -import org.eclipse.kuksa.extensions.updateRandomFloatValue +import org.eclipse.kuksa.connectivity.databroker.v1.provider.DataBrokerConnectorProvider import org.eclipse.kuksa.mocking.FriendlyVssPathListener import org.eclipse.kuksa.proto.v1.KuksaValV1 import org.eclipse.kuksa.proto.v1.Types diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/authentication/DataBrokerConnectorAuthenticationTest.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/authentication/DataBrokerConnectorAuthenticationTest.kt similarity index 97% rename from kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/authentication/DataBrokerConnectorAuthenticationTest.kt rename to kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/authentication/DataBrokerConnectorAuthenticationTest.kt index d292b66..c19c996 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/authentication/DataBrokerConnectorAuthenticationTest.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/authentication/DataBrokerConnectorAuthenticationTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 - 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ * */ -package org.eclipse.kuksa.connectivity.authentication +package org.eclipse.kuksa.connectivity.databroker.v1.authentication import io.grpc.StatusRuntimeException import io.kotest.assertions.nondeterministic.eventually @@ -26,14 +26,15 @@ import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe import io.kotest.matchers.string.shouldContain import io.kotest.matchers.types.instanceOf -import org.eclipse.kuksa.connectivity.databroker.DataBrokerConnectorProvider import org.eclipse.kuksa.connectivity.databroker.DataBrokerException import org.eclipse.kuksa.connectivity.databroker.docker.DataBrokerDockerContainer import org.eclipse.kuksa.connectivity.databroker.docker.SecureDataBrokerDockerContainer +import org.eclipse.kuksa.connectivity.databroker.v1.provider.DataBrokerConnectorProvider import org.eclipse.kuksa.connectivity.databroker.v1.request.FetchRequest import org.eclipse.kuksa.connectivity.databroker.v1.request.SubscribeRequest import org.eclipse.kuksa.connectivity.databroker.v1.request.UpdateRequest import org.eclipse.kuksa.mocking.FriendlyVssPathListener +import org.eclipse.kuksa.mocking.JwtType import org.eclipse.kuksa.proto.v1.Types import org.eclipse.kuksa.test.kotest.Authentication import org.eclipse.kuksa.test.kotest.Integration diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/extensions/DataBrokerTransporterExtensions.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/extensions/DataBrokerTransporterExtensions.kt similarity index 94% rename from kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/extensions/DataBrokerTransporterExtensions.kt rename to kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/extensions/DataBrokerTransporterExtensions.kt index c4aceb1..ac887a6 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/extensions/DataBrokerTransporterExtensions.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/extensions/DataBrokerTransporterExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ * */ -package org.eclipse.kuksa.extensions +package org.eclipse.kuksa.connectivity.databroker.v1.extensions import io.kotest.assertions.fail import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerTransporter diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectorProvider.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/provider/DataBrokerConnectorProvider.kt similarity index 89% rename from kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectorProvider.kt rename to kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/provider/DataBrokerConnectorProvider.kt index 63ee1a6..b88671a 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/DataBrokerConnectorProvider.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/provider/DataBrokerConnectorProvider.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,10 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker +package org.eclipse.kuksa.connectivity.databroker.v1.provider import io.grpc.ChannelCredentials import io.grpc.Grpc @@ -24,10 +25,13 @@ import io.grpc.ManagedChannel import io.grpc.ManagedChannelBuilder import io.grpc.TlsChannelCredentials import org.eclipse.kuksa.connectivity.authentication.JsonWebToken -import org.eclipse.kuksa.connectivity.authentication.JwtType +import org.eclipse.kuksa.connectivity.databroker.DATABROKER_HOST +import org.eclipse.kuksa.connectivity.databroker.DATABROKER_TIMEOUT_SECONDS +import org.eclipse.kuksa.connectivity.databroker.DATABROKER_TIMEOUT_UNIT import org.eclipse.kuksa.connectivity.databroker.docker.DEFAULT_PORT_INSECURE import org.eclipse.kuksa.connectivity.databroker.docker.DEFAULT_PORT_SECURE import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnector +import org.eclipse.kuksa.mocking.JwtType import org.eclipse.kuksa.model.TimeoutConfig import org.eclipse.kuksa.test.TestResourceFile import java.io.IOException @@ -35,6 +39,7 @@ import java.io.InputStream class DataBrokerConnectorProvider { lateinit var managedChannel: ManagedChannel + fun createInsecure( host: String = DATABROKER_HOST, port: Int = DEFAULT_PORT_INSECURE, diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/DataBrokerSubscriberTest.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/subscription/DataBrokerSubscriberTest.kt similarity index 96% rename from kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/DataBrokerSubscriberTest.kt rename to kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/subscription/DataBrokerSubscriberTest.kt index 5f3acae..5ef2919 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/subscription/DataBrokerSubscriberTest.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v1/subscription/DataBrokerSubscriberTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,10 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 + * */ -package org.eclipse.kuksa.connectivity.databroker.subscription +package org.eclipse.kuksa.connectivity.databroker.v1.subscription import io.kotest.assertions.nondeterministic.continually import io.kotest.assertions.nondeterministic.eventually @@ -27,16 +28,14 @@ import io.mockk.clearMocks import io.mockk.every import io.mockk.mockk import io.mockk.verify -import org.eclipse.kuksa.connectivity.databroker.DataBrokerConnectorProvider import org.eclipse.kuksa.connectivity.databroker.docker.DataBrokerDockerContainer import org.eclipse.kuksa.connectivity.databroker.docker.InsecureDataBrokerDockerContainer import org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerTransporter +import org.eclipse.kuksa.connectivity.databroker.v1.extensions.toggleBoolean +import org.eclipse.kuksa.connectivity.databroker.v1.extensions.updateRandomFloatValue +import org.eclipse.kuksa.connectivity.databroker.v1.extensions.updateRandomUint32Value import org.eclipse.kuksa.connectivity.databroker.v1.listener.VssPathListener -import org.eclipse.kuksa.connectivity.databroker.v1.subscription.DataBrokerSubscriber -import org.eclipse.kuksa.connectivity.databroker.v1.subscription.DataBrokerSubscription -import org.eclipse.kuksa.extensions.toggleBoolean -import org.eclipse.kuksa.extensions.updateRandomFloatValue -import org.eclipse.kuksa.extensions.updateRandomUint32Value +import org.eclipse.kuksa.connectivity.databroker.v1.provider.DataBrokerConnectorProvider import org.eclipse.kuksa.mocking.FriendlyVssNodeListener import org.eclipse.kuksa.mocking.FriendlyVssPathListener import org.eclipse.kuksa.pattern.listener.MultiListener diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/authentication/JwtType.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/mocking/JwtType.kt similarity index 91% rename from kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/authentication/JwtType.kt rename to kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/mocking/JwtType.kt index e87f9d6..4b7af9f 100644 --- a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/authentication/JwtType.kt +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/mocking/JwtType.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 - 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ * */ -package org.eclipse.kuksa.connectivity.authentication +package org.eclipse.kuksa.mocking import org.eclipse.kuksa.test.TestResourceFile import java.io.InputStream From 6a17c91e381fa10c404f9a3b494005b7c0927167 Mon Sep 17 00:00:00 2001 From: Andre Weber Date: Thu, 9 Jan 2025 14:37:32 +0100 Subject: [PATCH 8/9] test: Add kuksa.val.v2 tests --- .../databroker/v2/DataBrokerConnectionV2.kt | 41 ++- .../databroker/v2/DataBrokerTransporterV2.kt | 11 +- .../v2/extension/VALStubExtension.kt | 10 + .../provider/DataBrokerConnectorV2Provider.kt | 102 ++++++ .../v2/DataBrokerConnectionV2Test.kt | 337 ++++++++++++++++++ .../v2/DataBrokerConnectorV2Test.kt | 79 ++++ .../DataBrokerTransporterV2Extensions.kt | 87 +++++ .../v2/extensions/StringExtension.kt | 26 ++ .../provider/DataBrokerConnectorV2Provider.kt | 102 ++++++ 9 files changed, 788 insertions(+), 7 deletions(-) create mode 100644 kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/provider/DataBrokerConnectorV2Provider.kt create mode 100644 kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2Test.kt create mode 100644 kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectorV2Test.kt create mode 100644 kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extensions/DataBrokerTransporterV2Extensions.kt create mode 100644 kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extensions/StringExtension.kt create mode 100644 kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/provider/DataBrokerConnectorV2Provider.kt diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2.kt index 97e6565..7dc097f 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2.kt @@ -21,8 +21,10 @@ package org.eclipse.kuksa.connectivity.databroker.v2 import io.grpc.ConnectivityState import io.grpc.ManagedChannel +import io.grpc.stub.StreamObserver import kotlinx.coroutines.flow.Flow import org.eclipse.kuksa.connectivity.authentication.JsonWebToken +import org.eclipse.kuksa.connectivity.databroker.DataBrokerException import org.eclipse.kuksa.connectivity.databroker.DisconnectListener import org.eclipse.kuksa.connectivity.databroker.v2.request.ActuateRequestV2 import org.eclipse.kuksa.connectivity.databroker.v2.request.BatchActuateRequestV2 @@ -38,6 +40,11 @@ import org.eclipse.kuksa.proto.v2.KuksaValV2 import java.util.logging.Logger import kotlin.properties.Delegates +/** + * The DataBrokerConnection holds an active connection to the DataBroker. The Connection can be use to interact with the + * DataBroker. + */ +@Suppress("TooManyFunctions") // most methods are simply exposed from transporter layer class DataBrokerConnectionV2 internal constructor( private val managedChannel: ManagedChannel, private val dataBrokerTransporter: DataBrokerTransporterV2 = DataBrokerTransporterV2(managedChannel), @@ -77,6 +84,8 @@ class DataBrokerConnectionV2 internal constructor( * The server might respond with the following GRPC error codes: * NOT_FOUND if the requested signal doesn't exist * PERMISSION_DENIED if access is denied + * + * @throws DataBrokerException when an error occurs */ suspend fun fetchValue(request: FetchValueRequestV2): KuksaValV2.GetValueResponse { return dataBrokerTransporter.fetchValue(request.signalId) @@ -89,6 +98,9 @@ class DataBrokerConnectionV2 internal constructor( * The server might respond with the following GRPC error codes: * NOT_FOUND if any of the requested signals doesn't exist. * PERMISSION_DENIED if access is denied for any of the requested signals. + * + * @throws DataBrokerException when an error occurs + * */ suspend fun fetchValues(request: FetchValuesRequestV2): KuksaValV2.GetValuesResponse { return dataBrokerTransporter.fetchValues(request.signalIds) @@ -99,6 +111,8 @@ class DataBrokerConnectionV2 internal constructor( * Returns (GRPC error code): * NOT_FOUND if any of the signals are non-existent. * PERMISSION_DENIED if access is denied for any of the signals. + * + * @throws DataBrokerException when an error occurs */ fun subscribeById( request: SubscribeByIdRequestV2, @@ -115,6 +129,8 @@ class DataBrokerConnectionV2 internal constructor( * When subscribing the Broker shall immediately return the value for all * subscribed entries. If no value is available when subscribing a DataPoint * with value None shall be returned. + * + * @throws DataBrokerException when an error occurs */ fun subscribe( request: SubscribeRequestV2, @@ -132,6 +148,8 @@ class DataBrokerConnectionV2 internal constructor( * INVALID_ARGUMENT * - if the data type used in the request does not match the data type of the addressed signal * - if the requested value is not accepted, e.g. if sending an unsupported enum value + * + * @throws DataBrokerException when an error occurs */ suspend fun actuate(request: ActuateRequestV2): KuksaValV2.ActuateResponse { return dataBrokerTransporter.actuate(request.signalId, request.value) @@ -150,6 +168,7 @@ class DataBrokerConnectionV2 internal constructor( * - if the data type used in the request does not match the data type of the addressed signal * - if the requested value is not accepted, e.g. if sending an unsupported enum value * + * @throws DataBrokerException when an error occurs */ suspend fun batchActuate(request: BatchActuateRequestV2): KuksaValV2.BatchActuateResponse { return dataBrokerTransporter.batchActuate(request.signalIds, request.value) @@ -162,6 +181,8 @@ class DataBrokerConnectionV2 internal constructor( * * The server might respond with the following GRPC error codes: * NOT_FOUND if the specified root branch does not exist. + * + * @throws DataBrokerException when an error occurs */ suspend fun listMetadata(request: ListMetadataRequestV2): KuksaValV2.ListMetadataResponse { return dataBrokerTransporter.listMetadata(request.root, request.filter) @@ -178,6 +199,8 @@ class DataBrokerConnectionV2 internal constructor( * INVALID_ARGUMENT * - if the data type used in the request does not match the data type of the addressed signal * - if the published value is not accepted e.g. if sending an unsupported enum value + * + * @throws DataBrokerException when an error occurs */ suspend fun publishValue( request: PublishValueRequestV2, @@ -193,17 +216,29 @@ class DataBrokerConnectionV2 internal constructor( * The open stream is used for request / response type communication between the * provider and server (where the initiator of a request can vary). * Errors are communicated as messages in the stream. + * + * @throws DataBrokerException when an error occurs */ fun openProviderStream( - streamRequestFlow: Flow, - ): Flow { - return dataBrokerTransporter.openProviderStream(streamRequestFlow) + responseStream: StreamObserver, + ): StreamObserver { + return dataBrokerTransporter.openProviderStream(responseStream) } /** * Gets the server information. + * + * @throws DataBrokerException when an error occurs */ suspend fun fetchServerInfo(): KuksaValV2.GetServerInfoResponse { return dataBrokerTransporter.fetchServerInfo() } + + /** + * Disconnect from the DataBroker. + */ + fun disconnect() { + logger.finer("disconnect() called") + managedChannel.shutdownNow() + } } diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerTransporterV2.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerTransporterV2.kt index a19be8e..e6600fe 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerTransporterV2.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerTransporterV2.kt @@ -22,6 +22,7 @@ package org.eclipse.kuksa.connectivity.databroker.v2 import io.grpc.ConnectivityState import io.grpc.ManagedChannel import io.grpc.StatusException +import io.grpc.stub.StreamObserver import kotlinx.coroutines.flow.Flow import org.eclipse.kuksa.connectivity.authentication.JsonWebToken import org.eclipse.kuksa.connectivity.databroker.DataBrokerException @@ -29,6 +30,7 @@ import org.eclipse.kuksa.connectivity.databroker.v2.extension.withAuthentication import org.eclipse.kuksa.proto.v2.KuksaValV2 import org.eclipse.kuksa.proto.v2.Types import org.eclipse.kuksa.proto.v2.Types.Value +import org.eclipse.kuksa.proto.v2.VALGrpc import org.eclipse.kuksa.proto.v2.VALGrpcKt import org.eclipse.kuksa.proto.v2.actuateRequest import org.eclipse.kuksa.proto.v2.batchActuateRequest @@ -63,6 +65,7 @@ internal class DataBrokerTransporterV2( var jsonWebToken: JsonWebToken? = null private val coroutineStub: VALGrpcKt.VALCoroutineStub = VALGrpcKt.VALCoroutineStub(managedChannel) + private val asyncStub: VALGrpc.VALStub = VALGrpc.newStub(managedChannel) /** * Gets the latest value of a [signalId]. @@ -281,12 +284,12 @@ internal class DataBrokerTransporterV2( * Errors are communicated as messages in the stream. */ fun openProviderStream( - streamRequestFlow: Flow, - ): Flow { + responseStream: StreamObserver, + ): StreamObserver { return try { - coroutineStub + asyncStub .withAuthenticationInterceptor(jsonWebToken) - .openProviderStream(streamRequestFlow) + .openProviderStream(responseStream) } catch (e: StatusException) { throw DataBrokerException(e.message, e) } diff --git a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extension/VALStubExtension.kt b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extension/VALStubExtension.kt index 85cc3f0..61655f5 100644 --- a/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extension/VALStubExtension.kt +++ b/kuksa-java-sdk/src/main/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extension/VALStubExtension.kt @@ -24,6 +24,7 @@ import io.grpc.ClientInterceptor import io.grpc.Metadata import io.grpc.stub.MetadataUtils import org.eclipse.kuksa.connectivity.authentication.JsonWebToken +import org.eclipse.kuksa.proto.v2.VALGrpc import org.eclipse.kuksa.proto.v2.VALGrpcKt internal fun VALGrpcKt.VALCoroutineStub.withAuthenticationInterceptor( @@ -35,6 +36,15 @@ internal fun VALGrpcKt.VALCoroutineStub.withAuthenticationInterceptor( return withInterceptors(authenticationInterceptor) } +internal fun VALGrpc.VALStub.withAuthenticationInterceptor( + jsonWebToken: JsonWebToken?, +): VALGrpc.VALStub { + if (jsonWebToken == null) return this + + val authenticationInterceptor = clientInterceptor(jsonWebToken) + return withInterceptors(authenticationInterceptor) +} + private fun clientInterceptor(jsonWebToken: JsonWebToken): ClientInterceptor? { val authorizationHeader = Metadata.Key.of(HttpHeaders.AUTHORIZATION, Metadata.ASCII_STRING_MARSHALLER) diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/provider/DataBrokerConnectorV2Provider.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/provider/DataBrokerConnectorV2Provider.kt new file mode 100644 index 0000000..85047dc --- /dev/null +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/provider/DataBrokerConnectorV2Provider.kt @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.provider + +import io.grpc.ChannelCredentials +import io.grpc.Grpc +import io.grpc.ManagedChannel +import io.grpc.ManagedChannelBuilder +import io.grpc.TlsChannelCredentials +import org.eclipse.kuksa.connectivity.authentication.JsonWebToken +import org.eclipse.kuksa.connectivity.databroker.DATABROKER_HOST +import org.eclipse.kuksa.connectivity.databroker.DATABROKER_TIMEOUT_SECONDS +import org.eclipse.kuksa.connectivity.databroker.DATABROKER_TIMEOUT_UNIT +import org.eclipse.kuksa.connectivity.databroker.docker.DEFAULT_PORT_INSECURE +import org.eclipse.kuksa.connectivity.databroker.docker.DEFAULT_PORT_SECURE +import org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerConnectorV2 +import org.eclipse.kuksa.mocking.JwtType +import org.eclipse.kuksa.model.TimeoutConfig +import org.eclipse.kuksa.test.TestResourceFile +import java.io.IOException +import java.io.InputStream + +class DataBrokerConnectorV2Provider { + lateinit var managedChannel: ManagedChannel + + fun createInsecure( + host: String = DATABROKER_HOST, + port: Int = DEFAULT_PORT_INSECURE, + jwtFileStream: InputStream? = null, + ): DataBrokerConnectorV2 { + managedChannel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build() + + val jsonWebToken = jwtFileStream?.let { + val token = it.reader().readText() + JsonWebToken(token) + } + + return DataBrokerConnectorV2( + managedChannel, + jsonWebToken, + ).apply { + timeoutConfig = TimeoutConfig(DATABROKER_TIMEOUT_SECONDS, DATABROKER_TIMEOUT_UNIT) + } + } + + fun createSecure( + host: String = DATABROKER_HOST, + port: Int = DEFAULT_PORT_SECURE, + overrideAuthority: String = "", + rootCertFileStream: InputStream = TestResourceFile("tls/CA.pem").inputStream(), + jwtFileStream: InputStream? = JwtType.READ_WRITE_ALL.asInputStream(), + ): DataBrokerConnectorV2 { + val tlsCredentials: ChannelCredentials + try { + tlsCredentials = TlsChannelCredentials.newBuilder() + .trustManager(rootCertFileStream) + .build() + } catch (_: IOException) { + // Handle error + throw IOException("Could not create TLS credentials") + } + + val channelBuilder = Grpc + .newChannelBuilderForAddress(host, port, tlsCredentials) + + val hasOverrideAuthority = overrideAuthority.isNotEmpty() + if (hasOverrideAuthority) { + channelBuilder.overrideAuthority(overrideAuthority) + } + + managedChannel = channelBuilder.build() + + val jsonWebToken = jwtFileStream?.let { + val token = it.reader().readText() + JsonWebToken(token) + } + + return DataBrokerConnectorV2( + managedChannel, + jsonWebToken, + ).apply { + timeoutConfig = TimeoutConfig(DATABROKER_TIMEOUT_SECONDS, DATABROKER_TIMEOUT_UNIT) + } + } +} diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2Test.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2Test.kt new file mode 100644 index 0000000..6486c07 --- /dev/null +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectionV2Test.kt @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2 + +import io.grpc.ConnectivityState +import io.grpc.ManagedChannel +import io.grpc.StatusException +import io.grpc.stub.StreamObserver +import io.kotest.assertions.fail +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import io.kotest.matchers.shouldNotBe +import io.kotest.matchers.string.shouldContain +import io.kotest.matchers.types.instanceOf +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import kotlinx.coroutines.flow.first +import org.eclipse.kuksa.connectivity.databroker.DataBrokerException +import org.eclipse.kuksa.connectivity.databroker.DisconnectListener +import org.eclipse.kuksa.connectivity.databroker.docker.DataBrokerDockerContainer +import org.eclipse.kuksa.connectivity.databroker.docker.InsecureDataBrokerDockerContainer +import org.eclipse.kuksa.connectivity.databroker.v2.extensions.toSignalId +import org.eclipse.kuksa.connectivity.databroker.v2.extensions.updateRandomFloatValue +import org.eclipse.kuksa.connectivity.databroker.v2.provider.DataBrokerConnectorV2Provider +import org.eclipse.kuksa.connectivity.databroker.v2.request.ActuateRequestV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.FetchValueRequestV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.FetchValuesRequestV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.PublishValueRequestV2 +import org.eclipse.kuksa.connectivity.databroker.v2.request.SubscribeRequestV2 +import org.eclipse.kuksa.proto.v2.KuksaValV2.OpenProviderStreamRequest +import org.eclipse.kuksa.proto.v2.KuksaValV2.OpenProviderStreamResponse +import org.eclipse.kuksa.proto.v2.KuksaValV2.ProvideActuationRequest +import org.eclipse.kuksa.proto.v2.Types +import org.eclipse.kuksa.proto.v2.Types.SignalID +import org.eclipse.kuksa.test.kotest.Insecure +import org.eclipse.kuksa.test.kotest.InsecureDataBroker +import org.eclipse.kuksa.test.kotest.Integration +import org.junit.jupiter.api.Assertions +import kotlin.random.Random + +class DataBrokerConnectionV2Test : BehaviorSpec({ + tags(Integration, Insecure, InsecureDataBroker) + + var databrokerContainer: DataBrokerDockerContainer? = null + beforeSpec { + databrokerContainer = InsecureDataBrokerDockerContainer() + .apply { + start() + } + } + + afterSpec { + databrokerContainer?.stop() + } + + given("A successfully established connection to the DataBroker") { + val dataBrokerConnectorProvider = DataBrokerConnectorV2Provider() + val connector = dataBrokerConnectorProvider.createInsecure() + val dataBrokerConnection = connector.connect() + + val dataBrokerTransporter = + DataBrokerTransporterV2(dataBrokerConnectorProvider.managedChannel) + + `when`("trying to fetch multiple values") { + val signalIds = listOf( + "Vehicle.Acceleration.Longitudinal".toSignalId(), + "Vehicle.Acceleration.Vertical".toSignalId(), + ) + val randomFloat1 = createRandomFloatDatapoint() + val randomFloat2 = createRandomFloatDatapoint() + + dataBrokerTransporter.publishValue(signalIds[0], randomFloat1) + dataBrokerTransporter.publishValue(signalIds[1], randomFloat2) + + val request = FetchValuesRequestV2(signalIds) + val valuesResponse = dataBrokerConnection.fetchValues(request) + + then("the values should contain the correct information") { + valuesResponse.dataPointsCount shouldBe 2 + val dataPoint1 = valuesResponse.getDataPoints(0) + dataPoint1.value.float shouldBe randomFloat1.value.float + val dataPoint2 = valuesResponse.getDataPoints(1) + dataPoint2.value.float shouldBe randomFloat2.value.float + } + } + + `when`("no ActuationProvider exists for Vehicle.Cabin.Seat.Row1.DriverSide.Heating") { + `when`("trying to actuate Vehicle.Cabin.Seat.Row1.DriverSide.Heating") { + val signalId = "Vehicle.Cabin.Seat.Row1.DriverSide.Heating".toSignalId() + val value = Types.Value.newBuilder().setInt32(50).build() + + val request = ActuateRequestV2(signalId, value) + val result = runCatching { + dataBrokerConnection.actuate(request) + } + then("An Exception should be thrown") { + result.isFailure shouldBe true + val exception = result.exceptionOrNull()!! + exception shouldBe instanceOf(DataBrokerException::class) + exception.message shouldContain "UNAVAILABLE" + } + } + } + + `when`("an ActuationProvider exists for Vehicle.Cabin.Seat.Row1.DriverSide.Heating") { + val responseStream = object : StreamObserver { + override fun onNext(value: OpenProviderStreamResponse) { + // unimplemented + } + + override fun onError(t: Throwable) { + // unimplemented + } + + override fun onCompleted() { + // unimplemented + } + } + val requestStream = dataBrokerConnection.openProviderStream(responseStream) + + val signalId = "Vehicle.Cabin.Seat.Row1.DriverSide.Heating".toSignalId() + + val provideActuationRequest = ProvideActuationRequest.newBuilder() + .addActuatorIdentifiers(signalId) + .build() + val openProviderStreamRequest = OpenProviderStreamRequest.newBuilder() + .setProvideActuationRequest(provideActuationRequest) + .build() + requestStream.onNext(openProviderStreamRequest) + + `when`("trying to actuate Vehicle.Cabin.Seat.Row1.DriverSide.Heating") { + val value = Types.Value.newBuilder().setInt32(50).build() + + val request = ActuateRequestV2(signalId, value) + val result = runCatching { + dataBrokerConnection.actuate(request) + } + then("No Exception should be thrown") { + result.isSuccess shouldBe true + result.exceptionOrNull() shouldBe null + } + } + } + + and("a SubscribeRequest with a valid VSS Path") { + val vssPath = "Vehicle.Acceleration.Lateral" + val signalId = SignalID.newBuilder().setPath(vssPath).build() + + val initialValue = dataBrokerTransporter.updateRandomFloatValue(vssPath) + + val subscribeRequest = SubscribeRequestV2(listOf(vssPath)) + `when`("Subscribing to the VSS path") { + val responseFlow = dataBrokerConnection.subscribe(subscribeRequest) + + then("An initial update is sent") { + val subscribeResponse = responseFlow.first() + subscribeResponse shouldNotBe null + subscribeResponse.entriesCount shouldBe 1 + subscribeResponse.entriesMap[vssPath] shouldNotBe null + subscribeResponse.entriesMap[vssPath]?.value?.float shouldBe initialValue + } + + `when`("The observed VSS path changes") { + val randomFloatDatapoint = createRandomFloatDatapoint() + dataBrokerTransporter.publishValue(signalId, randomFloatDatapoint) + + then("The #onEntryChanged callback is triggered with the new value") { + val subscribeResponse = responseFlow.first() + subscribeResponse shouldNotBe null + subscribeResponse.entriesCount shouldBe 1 + subscribeResponse.entriesMap[vssPath] shouldNotBe null + subscribeResponse.entriesMap[vssPath]?.value?.float shouldBe randomFloatDatapoint.value.float + } + } + } + + val validDatapoint = createRandomFloatDatapoint() + + `when`("Updating the DataBroker property (VSS path) with a valid Datapoint") { + // make sure that the value is set and known to us + dataBrokerTransporter.publishValue(signalId, validDatapoint) + + and("When fetching it afterwards") { + val fetchRequest = FetchValueRequestV2(signalId) + val response = dataBrokerConnection.fetchValue(fetchRequest) + + then("The response contains the correctly set value") { + val dataPoint = response.dataPoint + val capturedValue = dataPoint.value.float + Assertions.assertEquals( + validDatapoint.value.float, + capturedValue, + 0.0001F, + ) + } + } + } + + `when`("publishing a Datapoint of a wrong/different type") { + val datapoint = createRandomIntDatapoint() + val updateRequest = PublishValueRequestV2(signalId, datapoint) + val result = runCatching { + dataBrokerConnection.publishValue(updateRequest) + } + + then("It should throw an Exception containing the Error INVALID_ARGUMENT") { + result.isFailure shouldBe true + val exception = result.exceptionOrNull()!! + exception shouldBe instanceOf(DataBrokerException::class) + exception.message shouldContain "INVALID_ARGUMENT" + } + + and("Fetching it afterwards") { + val fetchRequest = FetchValueRequestV2(signalId) + val getResponse = dataBrokerConnection.fetchValue(fetchRequest) + + then("The response still contains the previously set value") { + val dataPoint = getResponse.dataPoint + Assertions.assertEquals( + validDatapoint.value.float, + dataPoint.value.float, + 0.0001F, + ) + } + } + } + } + + and("An INVALID VSS Path") { + val invalidVssPath = "Vehicle.Some.Unknown.Path" + val invalidSignalId = SignalID.newBuilder().setPath(invalidVssPath).build() + + `when`("Trying to subscribe to the INVALID VSS path") { + val subscribeRequest = SubscribeRequestV2(listOf(invalidVssPath)) + + val result = runCatching { + dataBrokerConnection.subscribe(subscribeRequest).first() + } + + then("A DataBrokerException with error message 'NOT_FOUND' is thrown") { + result.isFailure shouldBe true + val exception = result.exceptionOrNull()!! + exception shouldBe instanceOf(StatusException::class) + exception.message shouldContain "NOT_FOUND" + } + } + + `when`("Trying to update the INVALID VSS Path") { + val datapoint = createRandomFloatDatapoint() + val updateRequest = PublishValueRequestV2(invalidSignalId, datapoint) + + val result = kotlin.runCatching { + dataBrokerConnection.publishValue(updateRequest) + } + + then("It should fail with an errorCode 404 (path not found)") { + result.onSuccess { fail("Should not succeed") } + } + } + + `when`("Trying to fetch the INVALID VSS path") { + val fetchRequest = FetchValueRequestV2(invalidSignalId) + + val result = runCatching { + dataBrokerConnection.fetchValue(fetchRequest) + } + + then("A DataBrokerException with error message 'NOT_FOUND' is thrown") { + result.isFailure shouldBe true + val exception = result.exceptionOrNull()!! + exception shouldBe instanceOf(DataBrokerException::class) + exception.message shouldContain "NOT_FOUND" + } + } + } + + // this test closes the connection, the connection can't be used afterward anymore + `when`("A DisconnectListener is registered successfully") { + val disconnectListener = mockk(relaxed = true) + val disconnectListeners = dataBrokerConnection.disconnectListeners + disconnectListeners.register(disconnectListener) + + `when`("The Connection is closed manually") { + dataBrokerConnection.disconnect() + + then("The DisconnectListener is triggered") { + verify { disconnectListener.onDisconnect() } + } + } + } + // connection is closed at this point + } + given("A DataBrokerConnection with a mocked ManagedChannel") { + val managedChannel = mockk(relaxed = true) + every { managedChannel.getState(any()) }.returns(ConnectivityState.READY) + val dataBrokerConnection = DataBrokerConnectionV2(managedChannel) + + `when`("Disconnect is called") { + dataBrokerConnection.disconnect() + + then("The Channel is shutDown") { + verify { managedChannel.shutdownNow() } + } + } + } +}) + +private val random = Random(System.currentTimeMillis()) +private fun createRandomFloatDatapoint(): Types.Datapoint { + val newValue = random.nextFloat() + val value = Types.Value.newBuilder().setFloat(newValue).build() + return Types.Datapoint.newBuilder().setValue(value).build() +} + +private fun createRandomIntDatapoint(): Types.Datapoint { + val newValue = random.nextInt() + val value = Types.Value.newBuilder().setInt32(newValue).build() + return Types.Datapoint.newBuilder().setValue(value).build() +} diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectorV2Test.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectorV2Test.kt new file mode 100644 index 0000000..730b637 --- /dev/null +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/DataBrokerConnectorV2Test.kt @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2 + +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldNotBe +import org.eclipse.kuksa.connectivity.databroker.DataBrokerException +import org.eclipse.kuksa.connectivity.databroker.docker.DataBrokerDockerContainer +import org.eclipse.kuksa.connectivity.databroker.docker.InsecureDataBrokerDockerContainer +import org.eclipse.kuksa.connectivity.databroker.v2.provider.DataBrokerConnectorV2Provider +import org.eclipse.kuksa.test.kotest.Insecure +import org.eclipse.kuksa.test.kotest.InsecureDataBroker +import org.eclipse.kuksa.test.kotest.Integration + +class DataBrokerConnectorV2Test : BehaviorSpec({ + tags(Integration, Insecure, InsecureDataBroker) + + var databrokerContainer: DataBrokerDockerContainer? = null + beforeSpec { + databrokerContainer = InsecureDataBrokerDockerContainer() + .apply { + start() + } + } + + afterSpec { + databrokerContainer?.stop() + } + + given("A DataBrokerConnectorV2Provider") { + val dataBrokerConnectorProvider = DataBrokerConnectorV2Provider() + + and("an insecure DataBrokerConnector with valid Host and Port") { + val dataBrokerConnector = dataBrokerConnectorProvider.createInsecure() + + `when`("Trying to establish an insecure connection") { + val connection = dataBrokerConnector.connect() + + then("It should return a valid connection") { + connection shouldNotBe null + } + } + } + + and("a DataBrokerConnector with INVALID Host and Port") { + val invalidHost = "0.0.0.0" + val invalidPort = 12345 + val dataBrokerConnector = dataBrokerConnectorProvider.createInsecure(invalidHost, invalidPort) + + `when`("Trying to establish a connection") { + val exception = shouldThrow { + dataBrokerConnector.connect() + } + + then("It should throw a DataBrokerException") { + exception shouldNotBe null + } + } + } + } +}) diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extensions/DataBrokerTransporterV2Extensions.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extensions/DataBrokerTransporterV2Extensions.kt new file mode 100644 index 0000000..cea7c3f --- /dev/null +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extensions/DataBrokerTransporterV2Extensions.kt @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2.extensions + +import io.kotest.assertions.fail +import org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerTransporterV2 +import org.eclipse.kuksa.proto.v2.Types +import org.eclipse.kuksa.proto.v2.Types.SignalID +import kotlin.random.Random + +internal suspend fun DataBrokerTransporterV2.updateRandomFloatValue( + vssPath: String, + maxValue: Int = 300, +): Float { + val random = Random(System.nanoTime()) + val randomValue = random.nextInt(maxValue) + val randomFloat = randomValue.toFloat() + + val signalID = SignalID.newBuilder().setPath(vssPath).build() + val value = Types.Value.newBuilder().setFloat(randomFloat).build() + val updatedDatapoint = Types.Datapoint.newBuilder().setValue(value).build() + + try { + publishValue(signalID, updatedDatapoint) + } catch (e: Exception) { + fail("Updating $vssPath to $randomFloat failed: $e") + } + + return randomFloat +} + +internal suspend fun DataBrokerTransporterV2.updateRandomUint32Value( + vssPath: String, + maxValue: Int = 300, +): Int { + val random = Random(System.nanoTime()) + val randomValue = random.nextInt(maxValue) + + val signalID = SignalID.newBuilder().setPath(vssPath).build() + val value = Types.Value.newBuilder().setUint32(randomValue).build() + val updatedDatapoint = Types.Datapoint.newBuilder().setValue(value).build() + + try { + publishValue(signalID, updatedDatapoint) + } catch (e: Exception) { + fail("Updating $vssPath to $randomValue failed: $e") + } + + return randomValue +} + +internal suspend fun DataBrokerTransporterV2.toggleBoolean(vssPath: String): Boolean { + var newBoolean: Boolean? = null + try { + val signalId = SignalID.newBuilder().setPath(vssPath).build() + val response = fetchValue(signalId) + + val currentBool = response.dataPoint.value.bool + + newBoolean = !currentBool + val value = Types.Value.newBuilder().setBool(newBoolean).build() + val newDatapoint = Types.Datapoint.newBuilder().setValue(value).build() + + publishValue(signalId, newDatapoint) + } catch (e: Exception) { + fail("Updating $vssPath to $newBoolean failed: $e") + } + + return newBoolean == true +} diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extensions/StringExtension.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extensions/StringExtension.kt new file mode 100644 index 0000000..678a934 --- /dev/null +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/extensions/StringExtension.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2.extensions + +import org.eclipse.kuksa.proto.v2.Types.SignalID + +fun String.toSignalId(): SignalID { + return SignalID.newBuilder().setPath(this).build() +} diff --git a/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/provider/DataBrokerConnectorV2Provider.kt b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/provider/DataBrokerConnectorV2Provider.kt new file mode 100644 index 0000000..ddb7152 --- /dev/null +++ b/kuksa-java-sdk/src/test/kotlin/org/eclipse/kuksa/connectivity/databroker/v2/provider/DataBrokerConnectorV2Provider.kt @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023 - 2025 Contributors to the Eclipse Foundation + * + * Licensed 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-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.connectivity.databroker.v2.provider + +import io.grpc.ChannelCredentials +import io.grpc.Grpc +import io.grpc.ManagedChannel +import io.grpc.ManagedChannelBuilder +import io.grpc.TlsChannelCredentials +import org.eclipse.kuksa.connectivity.authentication.JsonWebToken +import org.eclipse.kuksa.connectivity.databroker.DATABROKER_HOST +import org.eclipse.kuksa.connectivity.databroker.DATABROKER_TIMEOUT_SECONDS +import org.eclipse.kuksa.connectivity.databroker.DATABROKER_TIMEOUT_UNIT +import org.eclipse.kuksa.connectivity.databroker.docker.DEFAULT_PORT_INSECURE +import org.eclipse.kuksa.connectivity.databroker.docker.DEFAULT_PORT_SECURE +import org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerConnectorV2 +import org.eclipse.kuksa.mocking.JwtType +import org.eclipse.kuksa.model.TimeoutConfig +import org.eclipse.kuksa.test.TestResourceFile +import java.io.IOException +import java.io.InputStream + +class DataBrokerConnectorV2Provider { + lateinit var managedChannel: ManagedChannel + + fun createInsecure( + host: String = DATABROKER_HOST, + port: Int = DEFAULT_PORT_INSECURE, + jwtFileStream: InputStream? = null, + ): DataBrokerConnectorV2 { + managedChannel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build() + + val jsonWebToken = jwtFileStream?.let { + val token = it.reader().readText() + JsonWebToken(token) + } + + return DataBrokerConnectorV2( + managedChannel, + jsonWebToken, + ).apply { + timeoutConfig = TimeoutConfig(DATABROKER_TIMEOUT_SECONDS, DATABROKER_TIMEOUT_UNIT) + } + } + + fun createSecure( + host: String = DATABROKER_HOST, + port: Int = DEFAULT_PORT_SECURE, + overrideAuthority: String = "", + rootCertFileStream: InputStream = TestResourceFile("tls/CA.pem").inputStream(), + jwtFileStream: InputStream? = JwtType.READ_WRITE_ALL.asInputStream(), + ): DataBrokerConnectorV2 { + val tlsCredentials: ChannelCredentials + try { + tlsCredentials = TlsChannelCredentials.newBuilder() + .trustManager(rootCertFileStream) + .build() + } catch (_: IOException) { + // Handle error + throw IOException("Could not create TLS credentials") + } + + val channelBuilder = Grpc + .newChannelBuilderForAddress(host, port, tlsCredentials) + + val hasOverrideAuthority = overrideAuthority.isNotEmpty() + if (hasOverrideAuthority) { + channelBuilder.overrideAuthority(overrideAuthority) + } + + managedChannel = channelBuilder.build() + + val jsonWebToken = jwtFileStream?.let { + val token = it.reader().readText() + JsonWebToken(token) + } + + return DataBrokerConnectorV2( + managedChannel, + jsonWebToken, + ).apply { + timeoutConfig = TimeoutConfig(DATABROKER_TIMEOUT_SECONDS, DATABROKER_TIMEOUT_UNIT) + } + } +} From e4ea5384bd72461f7084e0ba982b35d347777be9 Mon Sep 17 00:00:00 2001 From: Andre Weber Date: Fri, 10 Jan 2025 14:30:36 +0100 Subject: [PATCH 9/9] docs: Add Documentation to README --- README.md | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3dc320a..f9958f5 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,41 @@ The KUKSA Java SDK allows you to interact with [VSS data](https://covesa.github. from the [KUKSA Databroker](https://github.com/eclipse-kuksa/kuksa-databroker/tree/main/) within a Java Application. The main functionality consists of fetching, updating and subscribing to VSS data. +Currently the following protocols are supported: +- kuksa.val.v1 +- kuksa.val.v2 + +## kuksa.val.v1 + +You can interact with the Databroker using the kuksa.val.v1 interface by using the +org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnector class. + +After successfully connecting the following methods are supported by org.eclipse.kuksa.connectivity.databroker.v1.DataBrokerConnection: +- subscribe(SubscribeRequest, VssPathListener) +- unsubscribe(SubscribeRequest, VssPathListener) +- subscribe(VssNodeSubscribeRequest, VssNodeListener) +- unsubscribe(VssNodeSubscribeRequest, VssNodeListener) +- fetch(FetchRequest): GetResponse +- fetch(VssNodeFetchRequest): T +- update(UpdateRequest): SetResponse +- update(VssNodeUpdateRequest): VssNodeUpdateResponse + +## kuksa.val.v2 + +You can interact with the Databroker using the kuksa.val.v1 interface by using the +org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerConnectorV2 class. + +After successfully connecting the following methods are supported by org.eclipse.kuksa.connectivity.databroker.v2.DataBrokerConnectionV2: +- fetchValue(FetchValueRequestV2): GetValueResponse +- fetchValues(FetchValuesRequestV2): GetValuesResponse +- subscribeById(SubscribeByIdRequestV2): Flow +- subscribe(SubscribeRequestV2): Flow +- actuate(ActuateRequestV2): ActuateResponse +- batchActuate(BatchActuateRequestV2): BatchActuateResponse +- listMetadata(ListMetadataRequestV2): ListMetadataResponse +- publishValue(PublishValueRequestV2): PublishValueResponse +- openProviderStream(StreamObserver): StreamObserver + ## Integration *app/build.gradle.kts* @@ -23,8 +58,7 @@ implementation("org.eclipse.kuksa:kuksa-java-sdk:") The latest release version can be seen [here](https://github.com/eclipse-kuksa/kuksa-java-sdk/releases). -See the [quickstart guide](https://github.com/eclipse-kuksa/kuksa-java-sdk/tree/main/docs/QUICKSTART.md) for -additional integration options. +See the [quickstart guide](https://github.com/eclipse-kuksa/kuksa-java-sdk/tree/main/docs/QUICKSTART.md) for additional integration options. ### Maven Central