Skip to content

Commit

Permalink
Add middleware abstraction (#62)
Browse files Browse the repository at this point in the history
Co-authored-by: Dominic Sudy <[email protected]>
  • Loading branch information
BjoernAtBosch and doosuu authored Jul 7, 2023
1 parent 0a4dc78 commit 59d1bd4
Show file tree
Hide file tree
Showing 35 changed files with 1,073 additions and 141 deletions.
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp",
"*.inc": "cpp"
"*.inc": "cpp",
"regex": "cpp",
"shared_mutex": "cpp"
}
}
4 changes: 2 additions & 2 deletions NOTICE-3RD-PARTY-CONTENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
|identify|2.5.24|MIT|
|idna|3.4|BSD|
|Jinja2|3.1.2|New BSD|
|lxml|4.9.2|New BSD|
|lxml|4.9.3|New BSD|
|MarkupSafe|2.1.3|New BSD|
|node-semver|0.6.1|MIT|
|nodeenv|1.8.0|BSD|
|patch-ng|1.17.4|MIT|
|platformdirs|3.8.0|MIT|
|platformdirs|3.8.1|MIT|
|pluginbase|1.0.1|BSD|
|pre-commit|2.20.0|MIT|
|Pygments|2.15.1|Simplified BSD|
Expand Down
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ With the runtime running in the background, you can run the app.
Open the `Run Task` view in VSCode and select `Local - VehicleApp (Dapr run)`.

### With debugging
You can simply launch the example in the Debugging Tab. Make sure the `VehicleApp - Debug (dapr run)` is selected at the top. After the selection is done, you can also simply hit `F5`, to start the debugging session.
You can simply launch the example in the Debugging Tab. Make sure the `Example - <example of your choice>` is selected at the top. After the selection is done, you can also simply hit `F5`, to start the debugging session.

*Note: This launch task will also make sure to re-build the app if it has been modified!*

Expand All @@ -69,6 +69,24 @@ docker run --net="host" --mount type=bind,source="$(pwd)"/.dapr,target=/.dapr da
docker run --rm -it --net="host" -e DAPR_GRPC_PORT=50001 -e DAPR_HTTP_PORT=3500 localhost:12345/vehicleapp:local
```

### Middleware configuration for the example apps

You can configure the middleware to be used (i.e. either `dapr` or `native`) via environment variables of the app processs.

| Middleware | Environment Variable | Default | Meaning
|------------|---------------------------------|---------------------|------------------------------------
| | `SDV_MIDDLEWARE_TYPE` | `dapr` | Defines the middleware to be used by the app (either `dapr` or `native`)
|
| Dapr | `SDV_MQTT_ADDRESS` | `localhost:1883` | Address of the MQTT broker - needs to be set explicitly as the C++ SDK does not support Dapr PubSub, yet
| | `SEATSERVICE_DAPR_APP_ID` | `seatservice` | Application id used by Dapr to discover the application providing the seat service
| | `VEHICLEDATABROKER_DAPR_APP_ID` | `vehicledatabroker` | Application id used by Dapr to discover the application providing the Kuksa (Vehicle) Data Broker
| | (`DAPR_GRPC_PORT`) | - | Usually, `DAPR_GRPC_PORT` and `DAPR_HTTP_PORT` don't need to be configured manually. They are set by `dapr run` when starting the app and its sidecar.
| | (`DAPR_HTTP_PORT`) | - | If you need to start your app separately, please make sure these environment variables are equally available to both the app and its sidecar with identical values (see above).
| |
| native | `SDV_MQTT_ADDRESS` | `localhost:1883` | Address of the MQTT broker
| | `SDV_SEATSERVICE_ADDRESS` | - | Address of the seat service
| | `SDV_VEHICLEDATABROKER_ADDRESS` | `localhost:55555` | Address of the Kuksa (Vehicle) Data Broker

## Documentation
* [Velocitas Development Model](https://eclipse.dev/velocitas/docs/concepts/development_model/)
* [Vehicle App SDK Overview](https://eclipse.dev/velocitas/docs/concepts/development_model/vehicle_app_sdk/)
Expand Down
2 changes: 1 addition & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

class VehicleAppCppSdkConan(ConanFile):
name = "vehicle-app-sdk"
version = "0.3.2"
version = "0.3.3"
license = "Apache-2.0"
url = "https://github.com/eclipse-velocitas/vehicle-app-cpp-sdk"
description = "The Vehicle App SDK for c++ allows to create Vehicle Apps from the Velocitas development model in the c++ programming language."
Expand Down
4 changes: 2 additions & 2 deletions examples/seat-adjuster/src/SeatAdjusterApp.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2022 Robert Bosch GmbH
* Copyright (c) 2022-2023 Robert Bosch GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
Expand Down Expand Up @@ -40,7 +40,7 @@ const auto STATUS_FAIL = 1;

SeatAdjusterApp::SeatAdjusterApp()
: VehicleApp(velocitas::IVehicleDataBrokerClient::createInstance("vehicledatabroker"),
velocitas::IPubSubClient::createInstance("localhost:1883", "SeatAdjusterApp"))
velocitas::IPubSubClient::createInstance("SeatAdjusterApp"))
, m_vehicleModel(std::make_shared<velocitas::Vehicle>()) {}

void SeatAdjusterApp::onStart() {
Expand Down
48 changes: 34 additions & 14 deletions examples/set-data-points/src/SetDataPointsApp.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2022 Robert Bosch GmbH
* Copyright (c) 2022-2023 Robert Bosch GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
Expand Down Expand Up @@ -30,25 +30,45 @@ namespace example {
class SetDataPointsApp : public velocitas::VehicleApp {
public:
SetDataPointsApp()
: VehicleApp(
velocitas::IVehicleDataBrokerClient::createInstance("vehicledatabroker"),
velocitas::IPubSubClient::createInstance("localhost:1883", "SetDataPointsApp")) {}
: VehicleApp(velocitas::IVehicleDataBrokerClient::createInstance("vehicledatabroker"),
velocitas::IPubSubClient::createInstance("SetDataPointsApp")) {}

void onStart() override {
velocitas::logger().info("Setting data points!");
// set a single data point
try {
velocitas::logger().info("Setting single data point ...");

Vehicle.Speed.set(100.0F)->await();

velocitas::logger().info("Setting single data point successfully done.");
} catch (velocitas::AsyncException& e) {
velocitas::logger().error("Error on setting single data point: {}", e.what());
}

// set multiple data points at the same time
Vehicle.setMany()
.add(Vehicle.Cabin.Seat.Row1.Pos1.Position, 1000)
.add(Vehicle.Cabin.Seat.Row1.Pos2.Position, 1000)
.apply()
->await();
try {
velocitas::logger().info("Setting batch of data points ...");

// set a single data point
Vehicle.Speed.set(100.0F)->await();
auto result = Vehicle.setMany()
.add(Vehicle.Cabin.Seat.Row1.Pos1.Position, 1000)
.add(Vehicle.Cabin.Seat.Row1.Pos2.Position, 1000)
.apply()
->await();

if (result.empty()) {
velocitas::logger().info("Setting batch of data points successfully done.");
} else {
velocitas::logger().error("Some data points of batch could not be set:");
for (auto datapointError : result) {
velocitas::logger().error(" '{}' -> {}", datapointError.first,
datapointError.second);
}
}
} catch (velocitas::AsyncException& e) {
velocitas::logger().error("Error on setting batch of data points: {}", e.what());
}

// get a single data point
Vehicle.Cabin.Seat.Row1.Pos1.Position.get()->await();
velocitas::logger().info("Done. (Press Ctrl+C to terminate the app.)");
}

private:
Expand Down
14 changes: 9 additions & 5 deletions examples/vehicle_model/Cabin/SeatService/SeatService.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2022 Robert Bosch GmbH
* Copyright (c) 2022-2023 Robert Bosch GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
Expand Down Expand Up @@ -81,11 +81,15 @@ Status toInternalStatus(grpc::Status status) {
}

SeatService::SeatService(Model* parent)
: Service("VehicleService", parent) {
: Service("SeatService", parent) {
m_asyncGrpcFacade = std::make_shared<SeatServiceAsyncGrpcFacade>(
grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()));
m_asyncGrpcFacade->setContextModifier(
[this](auto& context) { context.AddMetadata("dapr-app-id", getName()); });
grpc::CreateChannel(getLocation(), grpc::InsecureChannelCredentials()));
Middleware::Metadata metadata = getMiddlewareMetadata();
m_asyncGrpcFacade->setContextModifier([metadata](auto& context) {
for (auto metadatum : metadata) {
context.AddMetadata(metadatum.first, metadatum.second);
}
});
}

AsyncResultPtr_t<VoidResult> SeatService::move(const SeatService::Seat& seat) {
Expand Down
19 changes: 18 additions & 1 deletion sdk/include/sdk/IPubSubClient.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2022 Robert Bosch GmbH
* Copyright (c) 2022-2023 Robert Bosch GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
Expand Down Expand Up @@ -30,6 +30,23 @@ namespace velocitas {
*/
class IPubSubClient {
public:
/**
* @brief Create an instance of a pub/sub client according to the defined middleware
* configuration
*
* @param clientId used to identify the client at the pub/sub server
* @return std::shared_ptr<IPubSubClient> reference to the created pub/sub client
*/
static std::shared_ptr<IPubSubClient> createInstance(const std::string& clientId);

/**
* @brief Create a new instance of an MQTT client connecting to a broker at the specified
* address
*
* @param brokerUri address of the MQTT broker to connect to
* @param clientId used to identify the client at the MQTT broker
* @return std::shared_ptr<IPubSubClient> reference to the created MQTT client
*/
static std::shared_ptr<IPubSubClient> createInstance(const std::string& brokerUri,
const std::string& clientId);

Expand Down
6 changes: 5 additions & 1 deletion sdk/include/sdk/Model.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2022 Robert Bosch GmbH
* Copyright (c) 2022-2023 Robert Bosch GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
Expand All @@ -19,6 +19,7 @@

#include "sdk/DataPointBatch.h"
#include "sdk/Node.h"
#include "sdk/middleware/Middleware.h"

#include <string>

Expand All @@ -43,6 +44,9 @@ class Model : public Node {
class Service : public Node {
public:
using Node::Node;

std::string getLocation() const;
Middleware::Metadata getMiddlewareMetadata() const;
};

} // namespace velocitas
Expand Down
48 changes: 46 additions & 2 deletions sdk/include/sdk/Utils.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2022 Robert Bosch GmbH
* Copyright (c) 2022-2023 Robert Bosch GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
Expand All @@ -22,17 +22,61 @@

namespace velocitas {

/**
* @brief Get the value of the specified environment variable
*
* @param varName Name of the environment variable
* @param defaultValue Default if variable is not set
* @return std::string containing the value of the variable or the default value
*/
std::string getEnvVar(const std::string& varName, const std::string& defaultValue = "");

/**
* @brief Provides utility methods for handling strings.
*
*/
class StringUtils final {
public:
/**
* @brief Return the passed string converted to lowercase
*
* @param str string to be converted
* @return std::string having all uppercase letters contained in the passed string converted to
* lowercase
*/
static std::string toLower(const std::string& str);

/**
* @brief Return the passed string converted to uppercase
*
* @param str string to be converted
* @return std::string having all lowercase letters contained in the passed string converted to
* uppercase
*/
static std::string toUpper(const std::string& str);

/**
* @brief Concatenate the strings of the passed vector by adding the passed separator between
* each two of the array elements.
*
* Examples:
*
* stringVector | separator | result
* -------------------------|------------|--------------------
* [] (empty vector) | don't care | ""
* ["hello"] | don't care | "hello"
* ["hello", "world", "eh"] | ", " | "hello, world, eh"
* ["single", "ton"] | "" | "singleton"
*
* @param stringVector vector of strings to be concatenated
* @param separator string to be put between each two vector elements
* @return std::string containing the joined contents
*/
static std::string join(const std::vector<std::string>& stringVector,
const std::string& separator);

private:
StringUtils() = default;
StringUtils() = delete;
};

} // namespace velocitas
Expand Down
3 changes: 2 additions & 1 deletion sdk/include/sdk/dapr/DaprSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace velocitas::dapr {
* @brief Wait for the dapr sidecar to become available.
*
*/
void waitForSidecar();
[[deprecated("Don't call - this is handled by middleware internally. Will be removed soon!")]] void
waitForSidecar();

} // namespace velocitas::dapr
11 changes: 5 additions & 6 deletions sdk/include/sdk/grpc/VehicleDataBrokerClient.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2022 Robert Bosch GmbH
* Copyright (c) 2022-2023 Robert Bosch GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
Expand All @@ -20,6 +20,7 @@
#include "sdk/vdb/IVehicleDataBrokerClient.h"

#include <memory>
#include <string>
#include <vector>

namespace velocitas {
Expand All @@ -33,8 +34,8 @@ class BrokerAsyncGrpcFacade;
*/
class VehicleDataBrokerClient : public IVehicleDataBrokerClient {
public:
explicit VehicleDataBrokerClient(const std::string& vdbAddress, std::string vdbAppId);
explicit VehicleDataBrokerClient(const std::string& vdbAppId);
explicit VehicleDataBrokerClient(const std::string& vdbAddress, std::string vdbServiceName);
explicit VehicleDataBrokerClient(const std::string& vdbserviceName);

~VehicleDataBrokerClient() override;

Expand All @@ -52,11 +53,9 @@ class VehicleDataBrokerClient : public IVehicleDataBrokerClient {
AsyncSubscriptionPtr_t<DataPointReply> subscribe(const std::string& query) override;

private:
static std::string getVdbEndpointAddress();

std::shared_ptr<BrokerAsyncGrpcFacade> m_asyncBrokerFacade;
std::string m_vdbAppId;
};

} // namespace velocitas

#endif // VEHICLE_APP_SDK_VEHICLEDATABROKERCLIENT_H
Loading

0 comments on commit 59d1bd4

Please sign in to comment.