generic_subscriber.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #ifndef UAVCAN_NODE_GENERIC_SUBSCRIBER_HPP_INCLUDED
6 #define UAVCAN_NODE_GENERIC_SUBSCRIBER_HPP_INCLUDED
7 
8 #include <uavcan/error.hpp>
10 #include <uavcan/data_type.hpp>
14 #include <uavcan/debug.hpp>
17 #include <uavcan/marshal/types.hpp>
18 
19 namespace uavcan
20 {
38 template <typename DataType_>
40 {
42 
43  template <typename Ret, Ret(IncomingTransfer::*Fun) () const>
44  Ret safeget() const
45  {
46  if (_transfer_ == UAVCAN_NULLPTR)
47  {
48  return Ret();
49  }
50  return (_transfer_->*Fun)();
51  }
52 
53 protected:
55  : _transfer_(UAVCAN_NULLPTR)
56  { }
57 
59  : _transfer_(arg_transfer)
60  {
61  UAVCAN_ASSERT(arg_transfer != UAVCAN_NULLPTR);
62  }
63 
64 public:
65  typedef DataType_ DataType;
66 
68  {
69  return safeget<MonotonicTime, &IncomingTransfer::getMonotonicTimestamp>();
70  }
71  UtcTime getUtcTimestamp() const { return safeget<UtcTime, &IncomingTransfer::getUtcTimestamp>(); }
72  TransferPriority getPriority() const { return safeget<TransferPriority, &IncomingTransfer::getPriority>(); }
73  TransferType getTransferType() const { return safeget<TransferType, &IncomingTransfer::getTransferType>(); }
74  TransferID getTransferID() const { return safeget<TransferID, &IncomingTransfer::getTransferID>(); }
75  NodeID getSrcNodeID() const { return safeget<NodeID, &IncomingTransfer::getSrcNodeID>(); }
76  uint8_t getIfaceIndex() const { return safeget<uint8_t, &IncomingTransfer::getIfaceIndex>(); }
77  bool isAnonymousTransfer() const { return safeget<bool, &IncomingTransfer::isAnonymousTransfer>(); }
78 };
79 
84 template <typename Stream, typename DataType>
85 static Stream& operator<<(Stream& s, const ReceivedDataStructure<DataType>& rds)
86 {
87  s << "# Received struct ts_m=" << rds.getMonotonicTimestamp()
88  << " ts_utc=" << rds.getUtcTimestamp()
89  << " snid=" << int(rds.getSrcNodeID().get()) << "\n";
90  s << static_cast<const DataType&>(rds);
91  return s;
92 }
93 
94 
96 {
97 protected:
100 
102  : node_(node)
103  , failure_count_(0)
104  { }
105 
107 
108  int genericStart(TransferListener* listener, bool (Dispatcher::*registration_method)(TransferListener*));
109 
110  void stop(TransferListener* listener);
111 
112 public:
119 
120  INode& getNode() const { return node_; }
121 };
122 
127 template <typename DataSpec, typename DataStruct, typename TransferListenerType>
129 {
131 
132  // We need to break the inheritance chain here to implement lazy initialization
133  class TransferForwarder : public TransferListenerType
134  {
136 
138  {
139  obj_.handleIncomingTransfer(transfer);
140  }
141 
142  public:
144  const DataTypeDescriptor& data_type,
145  uint16_t max_buffer_size,
146  IPoolAllocator& allocator) :
147  TransferListenerType(obj.node_.getDispatcher().getTransferPerfCounter(),
148  data_type,
149  max_buffer_size,
150  allocator),
151  obj_(obj)
152  { }
153  };
154 
156 
157  int checkInit();
158 
159  void handleIncomingTransfer(IncomingTransfer& transfer);
160 
161  int genericStart(bool (Dispatcher::*registration_method)(TransferListener*));
162 
163 protected:
165  {
167 
169  ReceivedDataStructure<DataStruct>(arg_transfer)
170  { }
171  };
172 
174  { }
175 
176  virtual ~GenericSubscriber() { stop(); }
177 
178  virtual void handleReceivedDataStruct(ReceivedDataStructure<DataStruct>&) = 0;
179 
181  {
182  UAVCAN_TRACE("GenericSubscriber", "Start as message listener; dtname=%s", DataSpec::getDataTypeFullName());
183  return genericStart(&Dispatcher::registerMessageListener);
184  }
185 
187  {
188  UAVCAN_TRACE("GenericSubscriber", "Start as service request listener; dtname=%s",
189  DataSpec::getDataTypeFullName());
190  return genericStart(&Dispatcher::registerServiceRequestListener);
191  }
192 
194  {
195  UAVCAN_TRACE("GenericSubscriber", "Start as service response listener; dtname=%s",
196  DataSpec::getDataTypeFullName());
197  return genericStart(&Dispatcher::registerServiceResponseListener);
198  }
199 
205  {
206  forwarder_->allowAnonymousTransfers();
207  }
208 
213  void stop()
214  {
215  UAVCAN_TRACE("GenericSubscriber", "Stop; dtname=%s", DataSpec::getDataTypeFullName());
216  GenericSubscriberBase::stop(forwarder_);
217  }
218 
219  TransferListenerType* getTransferListener() { return forwarder_; }
220 };
221 
222 // ----------------------------------------------------------------------------
223 
224 /*
225  * GenericSubscriber
226  */
227 template <typename DataSpec, typename DataStruct, typename TransferListenerType>
229 {
230  if (forwarder_)
231  {
232  return 0;
233  }
234 
236  const DataTypeDescriptor* const descr =
237  GlobalDataTypeRegistry::instance().find(DataTypeKind(DataSpec::DataTypeKind), DataSpec::getDataTypeFullName());
238  if (descr == UAVCAN_NULLPTR)
239  {
240  UAVCAN_TRACE("GenericSubscriber", "Type [%s] is not registered", DataSpec::getDataTypeFullName());
241  return -ErrUnknownDataType;
242  }
243 
244  static const uint16_t MaxBufferSize = BitLenToByteLen<DataStruct::MaxBitLen>::Result;
245 
246  forwarder_.template construct<SelfType&, const DataTypeDescriptor&, uint16_t, IPoolAllocator&>
247  (*this, *descr, MaxBufferSize, node_.getAllocator());
248 
249  return 0;
250 }
251 
252 template <typename DataSpec, typename DataStruct, typename TransferListenerType>
254 {
255  ReceivedDataStructureSpec rx_struct(&transfer);
256 
257  /*
258  * Decoding into the temporary storage
259  */
260  BitStream bitstream(transfer);
261  ScalarCodec codec(bitstream);
262 
263  const int decode_res = DataStruct::decode(rx_struct, codec);
264 
265  // We don't need the data anymore, the memory can be reused from the callback:
266  transfer.release();
267 
268  if (decode_res <= 0)
269  {
270  UAVCAN_TRACE("GenericSubscriber", "Unable to decode the message [%i] [%s]",
271  decode_res, DataSpec::getDataTypeFullName());
272  failure_count_++;
274  return;
275  }
276 
277  /*
278  * Invoking the callback
279  */
280  handleReceivedDataStruct(rx_struct);
281 }
282 
283 template <typename DataSpec, typename DataStruct, typename TransferListenerType>
285 genericStart(bool (Dispatcher::*registration_method)(TransferListener*))
286 {
287  const int res = checkInit();
288  if (res < 0)
289  {
290  UAVCAN_TRACE("GenericSubscriber", "Initialization failure [%s]", DataSpec::getDataTypeFullName());
291  return res;
292  }
293  return GenericSubscriberBase::genericStart(forwarder_, registration_method);
294 }
295 
296 
297 }
298 
299 #endif // UAVCAN_NODE_GENERIC_SUBSCRIBER_HPP_INCLUDED
uavcan::Dispatcher::registerServiceResponseListener
bool registerServiceResponseListener(TransferListener *listener)
Definition: uc_dispatcher.cpp:334
types.hpp
data_type.hpp
uavcan::ReceivedDataStructure::getIfaceIndex
uint8_t getIfaceIndex() const
Definition: generic_subscriber.hpp:76
UAVCAN_NULLPTR
#define UAVCAN_NULLPTR
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:51
uavcan::BitStream
Definition: bit_stream.hpp:31
uavcan::Noncopyable
Definition: templates.hpp:46
templates.hpp
uavcan::ReceivedDataStructure::ReceivedDataStructure
ReceivedDataStructure(const IncomingTransfer *arg_transfer)
Definition: generic_subscriber.hpp:58
debug.hpp
uavcan::ReceivedDataStructure::ReceivedDataStructure
ReceivedDataStructure()
Definition: generic_subscriber.hpp:54
uavcan::GenericSubscriberBase::GenericSubscriberBase
GenericSubscriberBase(INode &node)
Definition: generic_subscriber.hpp:101
uavcan::uint32_t
std::uint32_t uint32_t
Definition: std.hpp:26
uavcan::UtcTime
Implicitly convertible to/from uavcan.Timestamp.
Definition: time.hpp:191
uavcan::Dispatcher::registerMessageListener
bool registerMessageListener(TransferListener *listener)
Definition: uc_dispatcher.cpp:314
uavcan::GenericSubscriberBase::failure_count_
uint32_t failure_count_
Definition: generic_subscriber.hpp:99
uavcan::operator<<
OStream & operator<<(OStream &s, long long x)
Definition: ostream.hpp:40
uavcan::NodeID::get
uint8_t get() const
Definition: transfer.hpp:132
uavcan::NodeID
Definition: transfer.hpp:112
uavcan::TransferType
TransferType
Definition: transfer.hpp:18
uavcan::BitLenToByteLen
Definition: type_util.hpp:42
uavcan::IncomingTransfer
Definition: transfer_listener.hpp:24
uavcan::INode::getDispatcher
Dispatcher & getDispatcher()
Definition: abstract_node.hpp:28
uavcan::GenericSubscriber::startAsMessageListener
int startAsMessageListener()
Definition: generic_subscriber.hpp:180
uavcan::GenericSubscriberBase::stop
void stop(TransferListener *listener)
Definition: uc_generic_subscriber.cpp:27
uavcan::GenericSubscriber::TransferForwarder::obj_
SelfType & obj_
Definition: generic_subscriber.hpp:135
uavcan::ReceivedDataStructure
Definition: generic_subscriber.hpp:39
UAVCAN_TRACE
#define UAVCAN_TRACE(...)
Definition: libuavcan/libuavcan/include/uavcan/debug.hpp:31
uavcan::GenericSubscriberBase::getFailureCount
uint32_t getFailureCount() const
Definition: generic_subscriber.hpp:118
uavcan::GenericSubscriber::startAsServiceRequestListener
int startAsServiceRequestListener()
Definition: generic_subscriber.hpp:186
uavcan::uint16_t
std::uint16_t uint16_t
Definition: std.hpp:25
uavcan::GlobalDataTypeRegistry::find
const DataTypeDescriptor * find(const char *name) const
Definition: uc_global_data_type_registry.cpp:144
uavcan::GenericSubscriber::genericStart
int genericStart(bool(Dispatcher::*registration_method)(TransferListener *))
Definition: generic_subscriber.hpp:285
uavcan::TransferID
Definition: transfer.hpp:71
uavcan::INode::getAllocator
virtual IPoolAllocator & getAllocator()=0
uavcan::Dispatcher
Definition: dispatcher.hpp:80
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
transfer_listener.hpp
uavcan::DataTypeDescriptor
Definition: data_type.hpp:130
uavcan::GenericSubscriber::TransferForwarder::handleIncomingTransfer
void handleIncomingTransfer(IncomingTransfer &transfer)
Definition: generic_subscriber.hpp:137
uavcan::ReceivedDataStructure::getUtcTimestamp
UtcTime getUtcTimestamp() const
Definition: generic_subscriber.hpp:71
lazy_constructor.hpp
uavcan::GenericSubscriber::ReceivedDataStructureSpec::ReceivedDataStructureSpec
ReceivedDataStructureSpec()
Definition: generic_subscriber.hpp:166
uavcan::IPoolAllocator
Definition: dynamic_memory.hpp:21
abstract_node.hpp
uavcan::ReceivedDataStructure::getPriority
TransferPriority getPriority() const
Definition: generic_subscriber.hpp:72
uavcan::ReceivedDataStructure::getTransferID
TransferID getTransferID() const
Definition: generic_subscriber.hpp:74
uavcan::GenericSubscriberBase::genericStart
int genericStart(TransferListener *listener, bool(Dispatcher::*registration_method)(TransferListener *))
Definition: uc_generic_subscriber.cpp:10
scalar_codec.hpp
UAVCAN_EXPORT
#define UAVCAN_EXPORT
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:108
uavcan::DataTypeKind
DataTypeKind
Definition: data_type.hpp:19
uavcan::INode
Definition: abstract_node.hpp:19
uavcan::TransferPriority
Definition: transfer.hpp:28
uavcan::GenericSubscriber::TransferForwarder::TransferForwarder
TransferForwarder(SelfType &obj, const DataTypeDescriptor &data_type, uint16_t max_buffer_size, IPoolAllocator &allocator)
Definition: generic_subscriber.hpp:143
uavcan::GenericSubscriber::forwarder_
LazyConstructor< TransferForwarder > forwarder_
Definition: generic_subscriber.hpp:155
uavcan::TransferListener
Definition: transfer_listener.hpp:99
int
int
Definition: libstubs.cpp:120
uavcan::GenericSubscriberBase::getNode
INode & getNode() const
Definition: generic_subscriber.hpp:120
uavcan::IncomingTransfer::release
virtual void release()
Definition: transfer_listener.hpp:54
uavcan::ReceivedDataStructure::getTransferType
TransferType getTransferType() const
Definition: generic_subscriber.hpp:73
uavcan::GenericSubscriber::ReceivedDataStructureSpec::ReceivedDataStructureSpec
ReceivedDataStructureSpec(const IncomingTransfer *arg_transfer)
Definition: generic_subscriber.hpp:168
uavcan::TransferPerfCounter::addError
void addError()
Definition: perf_counter.hpp:52
uavcan::GenericSubscriberBase::node_
INode & node_
Definition: generic_subscriber.hpp:98
pyuavcan_v0.dsdl.signature.s
s
Definition: signature.py:73
uavcan::Dispatcher::registerServiceRequestListener
bool registerServiceRequestListener(TransferListener *listener)
Definition: uc_dispatcher.cpp:324
global_data_type_registry.hpp
uavcan::Dispatcher::getTransferPerfCounter
const TransferPerfCounter & getTransferPerfCounter() const
Definition: dispatcher.hpp:236
uavcan::ReceivedDataStructure::getMonotonicTimestamp
MonotonicTime getMonotonicTimestamp() const
Definition: generic_subscriber.hpp:67
uavcan::GenericSubscriber::handleIncomingTransfer
void handleIncomingTransfer(IncomingTransfer &transfer)
Definition: generic_subscriber.hpp:253
uavcan::GenericSubscriberBase
Definition: generic_subscriber.hpp:95
uavcan::GenericSubscriber::TransferForwarder
Definition: generic_subscriber.hpp:133
uavcan::GenericSubscriber
Definition: generic_subscriber.hpp:128
pyuavcan_v0.introspect.node
node
Definition: introspect.py:398
uavcan::MonotonicTime
Definition: time.hpp:184
uavcan::GlobalDataTypeRegistry::instance
static GlobalDataTypeRegistry & instance()
Definition: uc_global_data_type_registry.cpp:128
uavcan::GenericSubscriber::GenericSubscriber
GenericSubscriber(INode &node)
Definition: generic_subscriber.hpp:173
uavcan
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:204
uavcan::ReceivedDataStructure::getSrcNodeID
NodeID getSrcNodeID() const
Definition: generic_subscriber.hpp:75
uavcan::ReceivedDataStructure::_transfer_
const IncomingTransfer *const _transfer_
Such weird name is necessary to avoid clashing with DataType fields.
Definition: generic_subscriber.hpp:41
uavcan::GlobalDataTypeRegistry::freeze
void freeze()
Definition: uc_global_data_type_registry.cpp:134
uavcan::ReceivedDataStructure::safeget
Ret safeget() const
Definition: generic_subscriber.hpp:44
uavcan::GenericSubscriber::allowAnonymousTransfers
void allowAnonymousTransfers()
Definition: generic_subscriber.hpp:204
uavcan::ScalarCodec
Definition: scalar_codec.hpp:20
uavcan::GenericSubscriber::ReceivedDataStructureSpec
Definition: generic_subscriber.hpp:164
uavcan::LazyConstructor
Definition: lazy_constructor.hpp:27
uavcan::GenericSubscriber::~GenericSubscriber
virtual ~GenericSubscriber()
Definition: generic_subscriber.hpp:176
uavcan::GenericSubscriberBase::~GenericSubscriberBase
~GenericSubscriberBase()
Definition: generic_subscriber.hpp:106
uavcan::ReceivedDataStructure::DataType
DataType_ DataType
Definition: generic_subscriber.hpp:65
uavcan::GenericSubscriber::startAsServiceResponseListener
int startAsServiceResponseListener()
Definition: generic_subscriber.hpp:193
UAVCAN_ASSERT
#define UAVCAN_ASSERT(x)
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:184
uavcan::GenericSubscriber::getTransferListener
TransferListenerType * getTransferListener()
Definition: generic_subscriber.hpp:219
uavcan::GenericSubscriber::SelfType
GenericSubscriber< DataSpec, DataStruct, TransferListenerType > SelfType
Definition: generic_subscriber.hpp:130
error.hpp
uavcan::ReceivedDataStructure::isAnonymousTransfer
bool isAnonymousTransfer() const
Definition: generic_subscriber.hpp:77
uavcan::GenericSubscriber::checkInit
int checkInit()
Definition: generic_subscriber.hpp:228


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:02