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> 35 : server_node_id(arg_server_node_id)
36 , transfer_id(arg_transfer_id)
53 template <
typename DataType>
69 , call_id_(arg_call_id)
70 , response_(arg_response)
73 UAVCAN_ASSERT((status_ == Success) || (status_ == ErrorTimeout));
88 const ResponseFieldType&
getResponse()
const {
return response_; }
96 template <
typename Stream,
typename DataType>
97 static Stream& operator<<(Stream& s, const ServiceCallResult<DataType>& scr)
99 s <<
"# Service call result [" << DataType::getDataTypeFullName() <<
"] " 100 << (scr.isSuccessful() ?
"OK" :
"FAILURE")
101 <<
" server_node_id=" <<
int(scr.getCallID().server_node_id.get())
102 <<
" tid=" <<
int(scr.getCallID().transfer_id.get()) <<
"\n";
103 if (scr.isSuccessful())
105 s << scr.getResponse();
150 return (&owner_ == &rhs.
owner_) && (id_ == rhs.
id_);
173 , request_timeout_(getDefaultRequestTimeout())
210 template <
typename DataType_,
211 #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 212 typename Callback_ = std::function<void (const ServiceCallResult<DataType_>&)>
246 UAVCAN_TRACE(
"ServiceClient::TimeoutCallbackCaller",
"Timeout from nid=%d, tid=%d, dtname=%s",
248 DataType::getDataTypeFullName());
252 ServiceCallResultType result(ServiceCallResultType::ErrorTimeout, state.
getCallID(),
265 virtual bool shouldAcceptFrame(
const RxFrame&
frame)
const;
267 void invokeCallback(ServiceCallResultType& result);
281 : SubscriberType(node)
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);
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_>
428 template <
typename DataType_,
typename Callback_>
435 ServiceCallResultType result(ServiceCallResultType::Success, call_id, response);
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 void removeAllWhere(Predicate predicate)
virtual void handleDeadline(MonotonicTime)
MonotonicDuration getTxTimeout() const
CallStateMatchingPredicate(ServiceCallID reference)
void cancelCall(ServiceCallID call_id)
bool operator==(const CallState &rhs) const
virtual bool shouldAcceptFrame(const RxFrame &frame) const
void setPriority(const TransferPriority prio)
TransferType getTransferType() const
ServiceCallID getCallID() const
CallState(INode &node, ServiceClientBase &owner, ServiceCallID call_id)
NodeID getSrcNodeID() const
DataType::Response ResponseType
ServiceCallID(NodeID arg_server_node_id, TransferID arg_transfer_id)
ServiceCallID getCallIDByIndex(unsigned index) const
bool operator()(const CallState &state) const
ServiceCallID call_id_
Identifies the call.
bool call(const std::string &service_name, MReq &req, MRes &res)
ServiceClient(INode &node, const Callback &callback=Callback())
ServiceClientBase & owner_
UAVCAN_EXPORT void handleFatalError(const char *msg)
static MonotonicDuration getMaxRequestTimeout()
void startWithDelay(MonotonicDuration delay)
bool operator==(const ServiceCallID rhs) const
void setTxTimeout(MonotonicDuration tx_timeout)
GenericPublisher< DataType, RequestType > PublisherType
TransferPriority getPriority() const
#define UAVCAN_TRACE(...)
TimeoutCallbackCaller(ServiceClient &arg_owner)
bool hasPendingCalls() const
TransferID getTransferID() const
const Callback & getCallback() const
const DataTypeDescriptor * data_type_descriptor_
This will be initialized at the time of first call.
Multiset< CallState > CallRegistry
GenericSubscriber< DataType, ResponseType, TransferListenerWithFilter > SubscriberType
UAVCAN_EXPORT const T & max(const T &a, const T &b)
ReceivedDataStructure< typename DataType::Response > ResponseFieldType
ServiceClientBase(INode &node)
ServiceCallID getCallID() const
void installAcceptanceFilter(const ITransferAcceptanceFilter *acceptance_filter)
TransferPriority getPriority() const
uint32_t getResponseFailureCount() const
MonotonicDuration getRequestTimeout() const
ServiceCallResult(Status arg_status, ServiceCallID arg_call_id, ResponseFieldType &arg_response)
NodeID getSrcNodeID() const
ServerSearchPredicate(NodeID nid)
UAVCAN_EXPORT const T & min(const T &a, const T &b)
T * find(Predicate predicate)
int init(TransferPriority priority)
const Status status_
Whether successful or not. Failure to decode the response causes timeout.
const ResponseFieldType & getResponse() const
void setCallback(const Callback &cb)
bool hasPendingCallToServer(NodeID server_node_id) const
int publish(const DataStruct &message, TransferType transfer_type, NodeID dst_node_id, MonotonicTime blocking_deadline=MonotonicTime())
const NodeID server_node_id
MonotonicDuration request_timeout_
void setRequestTimeout(MonotonicDuration timeout)
ResponseFieldType & response_
Returned data structure. Value undefined if the service call has failed.
ServiceCallResult< DataType > ServiceCallResultType
void invokeCallback(ServiceCallResultType &result)
static MonotonicDuration getDefaultRequestTimeout()
static MonotonicDuration getMinRequestTimeout()
bool operator()(const CallState &state) const
static MonotonicDuration fromMSec(int64_t ms)
unsigned getNumPendingCalls() const
ServiceClient< DataType, Callback > SelfType
TransferID getTransferID() const
T * getByIndex(unsigned index)
int addCallState(ServiceCallID call_id)
virtual void handleReceivedDataStruct(ReceivedDataStructure< ResponseType > &response)
virtual ~ServiceClientBase()
DataType::Request RequestType
static const TransferPriority MiddleLower
void setPriority(const TransferPriority prio)
int call(NodeID server_node_id, const RequestType &request)
void operator()(const CallState &state)
bool isSuccessful() const
void removeFirstWhere(Predicate predicate)
TransferType getTransferType() const
static bool hasTimedOutPredicate(const CallState &cs)
ResponseFieldType & getResponse()
CallRegistry call_registry_
static const uavcan::int16_t ErrLogic
Internal logic error.