Skip to content

Commit 701bfdf

Browse files
author
=
committed
merged changed into project branch
2 parents 397b246 + 8a6daf6 commit 701bfdf

File tree

18 files changed

+505
-341
lines changed

18 files changed

+505
-341
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,36 @@ cd build/Debug
7878
cmake --build . -- -j
7979
```
8080

81+
### With Conan for QNX
82+
83+
Before building **up-cpp** we need to build all dependencies from **up-conan-recipes**:
84+
85+
Please follow instruction for QNX build in file [up-conan-recipes/README.md](https://github.com/eclipse-uprotocol/up-conan-recipes/blob/main/README.md)
86+
87+
Pre-requisite:
88+
89+
* Build and install all **QNX build** dependencies from up-conan-recipes
90+
- https://github.com/eclipse-uprotocol/up-conan-recipes
91+
92+
```bash
93+
# setup path to up-conan-recipes
94+
export QNX_CONAN_ROOT=<path_to_up-conan-recipes>
95+
96+
# Install conan toolchain for QNX target
97+
#
98+
# <profile-name>: nto-7.1-aarch64-le, nto-7.1-x86_64, nto-8.0-aarch64-le, nto-8.0-x86_64
99+
# <version-number>: 1.0.0-rc0, 1.0.0, 1.0.1-rc1, 1.0.1
100+
#
101+
conan install -pr:h=$QNX_CONAN_ROOT/tools/profiles/<profile-name> --version=<version-number> --build=missing .
102+
103+
cmake --preset conan-release
104+
105+
cmake --build build/Release -- -j
106+
107+
# all tests you can find under build/Release/bin/
108+
# copy test binaries to your QNX target
109+
```
110+
81111
### Generate UT Coverage
82112

83113
To get code coverage, perform the steps above, but replace `cmake --preset...` with

conanfile.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from conan import ConanFile
2+
from conan.tools.cmake import CMakeToolchain, cmake_layout, CMakeDeps
3+
4+
class upCoreApiRecipe(ConanFile):
5+
name = "up-cpp"
6+
7+
# Optional metadata
8+
license = "Apache-2.0"
9+
author = "Contributors to the Eclipse Foundation <[email protected]>"
10+
url = "https://github.com/eclipse-uprotocol/up-cpp"
11+
description = "This library provides a C++ uProtocol API for the development of uEntities"
12+
topics = ("automotive", "iot", "uprotocol", "messaging")
13+
14+
# Binary configuration
15+
settings = "os", "compiler", "build_type", "arch"
16+
17+
def requirements(self):
18+
self.requires("protobuf/3.21.12")
19+
self.requires("spdlog/1.13.0")
20+
self.requires("up-core-api/[~1.6, include_prerelease]")
21+
self.test_requires("gtest/1.14.0")
22+
23+
def layout(self):
24+
cmake_layout(self)
25+
26+
def generate(self):
27+
deps = CMakeDeps(self)
28+
deps.generate()
29+
tc = CMakeToolchain(self)
30+
#all warnings have to be fixed
31+
tc.cache_variables["CMAKE_CXX_FLAGS_INIT"] = "-Wno-error=unused-but-set-variable -Wno-error=pedantic -Wno-error=conversion"
32+
tc.generate()

conanfile.txt

Lines changed: 0 additions & 14 deletions
This file was deleted.

include/up-cpp/client/usubscription/v3/RpcClientUSubscription.h

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -125,19 +125,7 @@ struct RpcClientUSubscription : USubscription {
125125

126126
private:
127127
std::shared_ptr<transport::UTransport> transport_;
128-
// Currently a single RpcClient can only send messages to a fixed UUri.
129-
// This forces us to use different RpcClients for different resource ids.
130-
// The alternative would be to create a new RpcClient for each request and
131-
// return a pointer to the client together with the InvokeProtoFuture to
132-
// keep it alive
133-
std::shared_ptr<communication::RpcClient> subscribe_client_;
134-
std::shared_ptr<communication::RpcClient> unsubscribe_client_;
135-
std::shared_ptr<communication::RpcClient> fetch_subscriptions_client_;
136-
std::shared_ptr<communication::RpcClient> fetch_subscribers_client_;
137-
std::shared_ptr<communication::RpcClient> register_for_notification_client_;
138-
std::shared_ptr<communication::RpcClient>
139-
unregister_for_notification_client_;
140-
128+
std::shared_ptr<communication::RpcClient> rpc_client_;
141129
USubscriptionUUriBuilder uuri_builder_;
142130
};
143131

include/up-cpp/communication/RpcClient.h

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ struct RpcClient {
5454
/// For guidance on the permeission_level and token parameters, see:
5555
/// https://github.com/eclipse-uprotocol/up-spec/blob/main/basics/permissions.adoc
5656
explicit RpcClient(std::shared_ptr<transport::UTransport> transport,
57-
v1::UUri&& method, v1::UPriority priority,
58-
std::chrono::milliseconds ttl,
57+
v1::UPriority priority, std::chrono::milliseconds ttl,
5958
std::optional<v1::UPayloadFormat> payload_format = {},
6059
std::optional<uint32_t> permission_level = {},
6160
std::optional<std::string> token = {});
@@ -113,6 +112,7 @@ struct RpcClient {
113112

114113
/// @brief Invokes an RPC method by sending a request message.
115114
///
115+
/// @param The method that will be invoked
116116
/// @param A Payload builder containing the payload to be sent with the
117117
/// request.
118118
/// @param A callback that will be called with the result.
@@ -124,11 +124,13 @@ struct RpcClient {
124124
/// * A UStatus based on the commstatus received in the response
125125
/// message (if not OK).
126126
/// * A UMessage containing the response from the RPC target.
127-
[[nodiscard]] InvokeHandle invokeMethod(datamodel::builder::Payload&&,
127+
[[nodiscard]] InvokeHandle invokeMethod(const v1::UUri&,
128+
datamodel::builder::Payload&&,
128129
Callback&&);
129130

130131
/// @brief Invokes an RPC method by sending a request message.
131132
///
133+
/// @param The method that will be invoked
132134
/// @param A Payload builder containing the payload to be sent with the
133135
/// request.
134136
///
@@ -141,13 +143,15 @@ struct RpcClient {
141143
/// * A UStatus based on the commstatus received in the response
142144
/// message (if not OK).
143145
/// * A UMessage containing the response from the RPC target.
144-
[[nodiscard]] InvokeFuture invokeMethod(datamodel::builder::Payload&&);
146+
[[nodiscard]] InvokeFuture invokeMethod(const v1::UUri&,
147+
datamodel::builder::Payload&&);
145148

146149
/// @brief Invokes an RPC method by sending a request message.
147150
///
148151
/// Request is sent with an empty payload. Can only be called if no payload
149152
/// format was provided at construction time.
150153
///
154+
/// @param The method that will be invoked
151155
/// @param A callback that will be called with the result.
152156
///
153157
/// @post The provided callback will be called with one of:
@@ -157,13 +161,14 @@ struct RpcClient {
157161
/// * A UStatus based on the commstatus received in the response
158162
/// message (if not OK).
159163
/// * A UMessage containing the response from the RPC target.
160-
[[nodiscard]] InvokeHandle invokeMethod(Callback&&);
164+
[[nodiscard]] InvokeHandle invokeMethod(const v1::UUri&, Callback&&);
161165

162166
/// @brief Invokes an RPC method by sending a request message.
163167
///
164168
/// Request is sent with an empty payload. Can only be called if no payload
165169
/// format was provided at construction time.
166170
///
171+
/// @param The method that will be invoked
167172
/// @remarks This is a wrapper around the callback form of invokeMethod.
168173
///
169174
/// @returns A promised future that can resolve to one of:
@@ -173,7 +178,83 @@ struct RpcClient {
173178
/// * A UStatus based on the commstatus received in the response
174179
/// message (if not OK).
175180
/// * A UMessage containing the response from the RPC target.
176-
[[nodiscard]] InvokeFuture invokeMethod();
181+
[[nodiscard]] InvokeFuture invokeMethod(const v1::UUri&);
182+
183+
template <typename R>
184+
InvokeHandle invokeMethodToProto(const v1::UUri& method,
185+
const R& request_message,
186+
Callback&& callback) {
187+
auto payload_or_status =
188+
uprotocol::utils::ProtoConverter::protoToPayload(request_message);
189+
190+
if (!payload_or_status.has_value()) {
191+
return {};
192+
}
193+
194+
datamodel::builder::Payload tmp_payload(payload_or_status.value());
195+
auto handle = invokeMethod(
196+
builder_.withMethod(method).build(std::move(tmp_payload)),
197+
std::move(callback));
198+
199+
return handle;
200+
}
201+
202+
template <typename T, typename R>
203+
InvokeProtoFuture<T> invokeMethodToProto(const v1::UUri& method,
204+
const R& request_message) {
205+
auto result_promise =
206+
std::make_shared<std::promise<ResponseOrStatus<T>>>();
207+
auto future = result_promise->get_future();
208+
auto handle = invokeMethodToProto(
209+
method, request_message,
210+
[result_promise](const MessageOrStatus& message_or_status) {
211+
if (!message_or_status.has_value()) {
212+
result_promise->set_value(ResponseOrStatus<T>(
213+
UnexpectedStatus(message_or_status.error())));
214+
return;
215+
}
216+
auto response_or_status =
217+
utils::ProtoConverter::extractFromProtobuf<T>(
218+
message_or_status.value());
219+
220+
if (!response_or_status.has_value()) {
221+
spdlog::error(
222+
"invokeProtoMethod: Error when extracting response "
223+
"from "
224+
"protobuf.");
225+
result_promise->set_value(response_or_status);
226+
return;
227+
}
228+
229+
result_promise->set_value(
230+
ResponseOrStatus<T>(response_or_status.value()));
231+
});
232+
233+
return {std::move(future), std::move(handle)};
234+
}
235+
236+
template <typename R>
237+
InvokeFuture invokeMethodToProto(const v1::UUri& method,
238+
const R& request_message) {
239+
auto result_promise =
240+
std::make_shared<std::promise<ResponseOrStatus<v1::UMessage>>>();
241+
auto future = result_promise->get_future();
242+
243+
auto handle = invokeMethodToProto(
244+
method, request_message,
245+
[result_promise](const MessageOrStatus& message_or_status) {
246+
if (!message_or_status.has_value()) {
247+
result_promise->set_value(ResponseOrStatus<v1::UMessage>(
248+
UnexpectedStatus(message_or_status.error())));
249+
return;
250+
}
251+
252+
result_promise->set_value(
253+
ResponseOrStatus<v1::UMessage>(message_or_status.value()));
254+
});
255+
256+
return {std::move(future), std::move(handle)};
257+
}
177258

178259
template <typename R>
179260
InvokeHandle invokeProtoMethod(const R& request_message,

include/up-cpp/datamodel/builder/UMessage.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,13 @@
2323
#include <string>
2424
#include <vector>
2525

26+
#include "up-cpp/communication/NotificationSink.h"
2627
#include "up-cpp/datamodel/builder/Uuid.h"
2728

29+
namespace uprotocol::communication {
30+
struct RpcClient;
31+
}
32+
2833
namespace uprotocol::datamodel::builder {
2934

3035
/// @brief Interface for composing UMessage objects
@@ -38,6 +43,7 @@ namespace uprotocol::datamodel::builder {
3843
/// instance can be held and reused by calling .build(payload)
3944
/// for each new set of message data.
4045
struct UMessageBuilder {
46+
friend struct communication::RpcClient;
4147
/// @brief Pre-populates a message builder with the attributes of a
4248
/// "publish" type message.
4349
///
@@ -103,6 +109,15 @@ struct UMessageBuilder {
103109
/// @returns UMessageBuilder configured to build a "response" message
104110
static UMessageBuilder response(const v1::UMessage& request);
105111

112+
/// @brief Set the method attribute for built messages.
113+
///
114+
/// @param The method to use when building messages.
115+
///
116+
/// @throws std::out_of_range if the value is not a valid method UUri
117+
///
118+
/// @returns A reference to this UMessageBuilder
119+
UMessageBuilder& withMethod(const v1::UUri&);
120+
106121
/// @brief Set the message priority attribute for built messages.
107122
///
108123
/// If not called, the default value as specified in

src/client/usubscription/v3/Consumer.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,7 @@ v1::UStatus Consumer::subscribe(
9494
v1::UPriority priority, std::chrono::milliseconds subscription_request_ttl,
9595
ListenCallback&& callback) {
9696
rpc_client_ = std::make_unique<communication::RpcClient>(
97-
transport_, uSubscriptionUUriBuilder_.getServiceUriWithResourceId(1),
98-
priority, subscription_request_ttl);
97+
transport_, priority, subscription_request_ttl);
9998

10099
auto on_response = [this](const auto& maybe_response) {
101100
if (maybe_response.has_value() &&
@@ -113,8 +112,9 @@ v1::UStatus Consumer::subscribe(
113112
SubscriptionRequest const subscription_request = buildSubscriptionRequest();
114113
auto payload = datamodel::builder::Payload(subscription_request);
115114

116-
rpc_handle_ =
117-
rpc_client_->invokeMethod(std::move(payload), std::move(on_response));
115+
rpc_handle_ = rpc_client_->invokeMethod(
116+
uSubscriptionUUriBuilder_.getServiceUriWithResourceId(1),
117+
std::move(payload), std::move(on_response));
118118

119119
// Create a L2 subscription
120120
auto result = communication::Subscriber::subscribe(
@@ -138,8 +138,7 @@ UnsubscribeRequest Consumer::buildUnsubscriptionRequest() {
138138
void Consumer::unsubscribe(v1::UPriority priority,
139139
std::chrono::milliseconds request_ttl) {
140140
rpc_client_ = std::make_unique<communication::RpcClient>(
141-
transport_, uSubscriptionUUriBuilder_.getServiceUriWithResourceId(2),
142-
priority, request_ttl);
141+
transport_, priority, request_ttl);
143142

144143
auto on_response = [](const auto& maybe_response) {
145144
if (!maybe_response.has_value()) {
@@ -150,8 +149,9 @@ void Consumer::unsubscribe(v1::UPriority priority,
150149
UnsubscribeRequest const unsubscribe_request = buildUnsubscriptionRequest();
151150
auto payload = datamodel::builder::Payload(unsubscribe_request);
152151

153-
rpc_handle_ =
154-
rpc_client_->invokeMethod(std::move(payload), std::move(on_response));
152+
rpc_handle_ = rpc_client_->invokeMethod(
153+
uSubscriptionUUriBuilder_.getServiceUriWithResourceId(2),
154+
std::move(payload), std::move(on_response));
155155

156156
subscriber_.reset();
157157
}

0 commit comments

Comments
 (0)