Go to the documentation of this file.
5 #ifndef UAVCAN_NODE_SERVICE_CLIENT_HPP_INCLUDED
6 #define UAVCAN_NODE_SERVICE_CLIENT_HPP_INCLUDED
13 #if !defined(UAVCAN_CPP_VERSION) || !defined(UAVCAN_CPP11)
14 # error UAVCAN_CPP_VERSION
17 #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
18 # include <functional>
53 template <
typename DataType>
69 , call_id_(arg_call_id)
70 , response_(arg_response)
73 UAVCAN_ASSERT((status_ == Success) || (status_ == ErrorTimeout));
96 template <
typename Stream,
typename DataType>
99 s <<
"# Service call result [" << DataType::getDataTypeFullName() <<
"] "
210 template <
typename DataType_,
211 #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
212 typename Callback_ = std::function<void (
const ServiceCallResult<DataType_>&)>
214 typename Callback_ = void (*)(
const ServiceCallResult<DataType_>&)
246 UAVCAN_TRACE(
"ServiceClient::TimeoutCallbackCaller",
"Timeout from nid=%d, tid=%d, dtname=%s",
248 DataType::getDataTypeFullName());
265 virtual bool shouldAcceptFrame(
const RxFrame&
frame)
const;
283 , call_registry_(
node.getAllocator())
284 , publisher_(
node, getDefaultRequestTimeout())
285 , callback_(callback)
288 setRequestTimeout(getDefaultRequestTimeout());
290 UAVCAN_ASSERT(getRequestTimeout() == getDefaultRequestTimeout());
302 return publisher_.
init();
312 return publisher_.
init(priority);
325 int call(
NodeID server_node_id,
const RequestType& request);
341 void cancelAllCalls();
346 bool hasPendingCallToServer(
NodeID server_node_id)
const;
387 timeout =
max(timeout, getMinRequestTimeout());
388 timeout =
min(timeout, getMaxRequestTimeout());
405 template <
typename DataType_,
typename Callback_>
408 if (coerceOrFallback<bool>(callback_,
true))
418 template <
typename DataType_,
typename Callback_>
424 frame.getTransferID())));
428 template <
typename DataType_,
typename Callback_>
436 invokeCallback(result);
440 template <
typename DataType_,
typename Callback_>
443 UAVCAN_TRACE(
"ServiceClient",
"Shared deadline event received");
447 TimeoutCallbackCaller callback_caller(*
this);
448 call_registry_.template forEach<TimeoutCallbackCaller&>(callback_caller);
460 SubscriberType::stop();
464 template <
typename DataType_,
typename Callback_>
469 const int subscriber_res = SubscriberType::startAsServiceResponseListener();
470 if (subscriber_res < 0)
472 UAVCAN_TRACE(
"ServiceClient",
"Failed to start the subscriber, error: %i", subscriber_res);
473 return subscriber_res;
480 SubscriberType::stop();
487 template <
typename DataType_,
typename Callback_>
491 return call(server_node_id, request,
dummy);
494 template <
typename DataType_,
typename Callback_>
498 if (!coerceOrFallback<bool>(callback_,
true))
501 return -ErrInvalidConfiguration;
508 prepareToCall(SubscriberType::getNode(), DataType::getDataTypeFullName(), server_node_id, out_call_id);
511 UAVCAN_TRACE(
"ServiceClient",
"Failed to prepare the call, error: %i", prep_res);
518 const int call_state_res = addCallState(out_call_id);
519 if (call_state_res < 0)
521 UAVCAN_TRACE(
"ServiceClient",
"Failed to add call state, error: %i", call_state_res);
522 return call_state_res;
533 cancelCall(out_call_id);
543 if (publisher_res < 0)
545 cancelCall(out_call_id);
546 return publisher_res;
550 return publisher_res;
553 template <
typename DataType_,
typename Callback_>
559 SubscriberType::stop();
563 template <
typename DataType_,
typename Callback_>
566 call_registry_.
clear();
567 SubscriberType::stop();
570 template <
typename DataType_,
typename Callback_>
576 template <
typename DataType_,
typename Callback_>
585 #endif // UAVCAN_NODE_SERVICE_CLIENT_HPP_INCLUDED
const std::string response
void removeFirstWhere(Predicate predicate)
ReceivedDataStructure< typename DataType::Response > ResponseFieldType
int addCallState(ServiceCallID call_id)
void removeAllWhere(Predicate predicate)
bool call(const std::string &service_name, MReq &req, MRes &res)
ServiceCallID getCallIDByIndex(unsigned index) const
virtual void handleDeadline(MonotonicTime)
int prepareToCall(INode &node, const char *dtname, NodeID server_node_id, ServiceCallID &out_call_id)
void cancelCall(ServiceCallID call_id)
virtual bool shouldAcceptFrame(const RxFrame &frame) const
void setTxTimeout(MonotonicDuration tx_timeout)
static MonotonicDuration getDefaultRequestTimeout()
ServiceCallID call_id_
Identifies the call.
ServiceCallID getCallID() const
ServiceCallID getCallID() const
CallRegistry call_registry_
virtual ~ServiceClientBase()
ServiceClient(INode &node, const Callback &callback=Callback())
OStream & operator<<(OStream &s, long long x)
GenericPublisher< DataType, RequestType > PublisherType
TransferPriority getPriority() const
@ TransferTypeServiceResponse
static MonotonicDuration fromMSec(int64_t ms)
void installAcceptanceFilter(const ITransferAcceptanceFilter *acceptance_filter)
DataType::Response ResponseType
virtual void handleDeadline(MonotonicTime)
ResponseFieldType & response_
Returned data structure. Value undefined if the service call has failed.
#define UAVCAN_TRACE(...)
GenericSubscriber< DataType, ResponseType, TransferListenerWithFilter > SubscriberType
@ TransferTypeServiceRequest
int publish(const DataStruct &message, TransferType transfer_type, NodeID dst_node_id, MonotonicTime blocking_deadline=MonotonicTime())
uint32_t getResponseFailureCount() const
static const TransferPriority MiddleLower
const Callback & getCallback() const
T * find(Predicate predicate)
const Status status_
Whether successful or not. Failure to decode the response causes timeout.
bool hasPendingCalls() const
static const uavcan::int16_t ErrLogic
Internal logic error.
ServiceCallResult(Status arg_status, ServiceCallID arg_call_id, ResponseFieldType &arg_response)
ResponseFieldType & getResponse()
Multiset< CallState > CallRegistry
CallStateMatchingPredicate(ServiceCallID reference)
const UAVCAN_EXPORT T & max(const T &a, const T &b)
bool operator==(const CallState &rhs) const
ServiceClientBase(INode &node)
CallState(INode &node, ServiceClientBase &owner, ServiceCallID call_id)
const UAVCAN_EXPORT T & min(const T &a, const T &b)
int init(TransferPriority priority)
T * getByIndex(unsigned index)
ServerSearchPredicate(NodeID nid)
static bool hasTimedOutPredicate(const CallState &cs)
const ResponseFieldType & getResponse() const
static MonotonicDuration getMinRequestTimeout()
static MonotonicDuration getMaxRequestTimeout()
bool isSuccessful() const
const DataTypeDescriptor * data_type_descriptor_
This will be initialized at the time of first call.
TransferPriority getPriority() const
TimeoutCallbackCaller(ServiceClient &arg_owner)
bool hasPendingCallToServer(NodeID server_node_id) const
unsigned getNumPendingCalls() const
MonotonicDuration getRequestTimeout() const
ServiceClient< DataType, Callback > SelfType
bool operator()(const CallState &state) const
void setRequestTimeout(MonotonicDuration timeout)
const NodeID server_node_id
virtual void handleReceivedDataStruct(ReceivedDataStructure< ResponseType > &response)
ServiceCallID(NodeID arg_server_node_id, TransferID arg_transfer_id)
void startWithDelay(MonotonicDuration delay)
ServiceClientBase & owner_
void setCallback(const Callback &cb)
UAVCAN_EXPORT void handleFatalError(const char *msg)
bool operator()(const CallState &state) const
ServiceCallResult< DataType > ServiceCallResultType
MonotonicDuration getTxTimeout() const
MonotonicDuration request_timeout_
void setPriority(const TransferPriority prio)
void setPriority(const TransferPriority prio)
int call(NodeID server_node_id, const RequestType &request)
bool operator==(const ServiceCallID rhs) const
Scheduler & getScheduler() const
void invokeCallback(ServiceCallResultType &result)
void operator()(const CallState &state)
DataType::Request RequestType