Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UAVCAN UAVCAN_Subscriber
generic_publisher.hpp
00001 /* 00002 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #ifndef UAVCAN_NODE_GENERIC_PUBLISHER_HPP_INCLUDED 00006 #define UAVCAN_NODE_GENERIC_PUBLISHER_HPP_INCLUDED 00007 00008 #include <uavcan/error.hpp> 00009 #include <uavcan/node/abstract_node.hpp> 00010 #include <uavcan/data_type.hpp> 00011 #include <uavcan/node/global_data_type_registry.hpp> 00012 #include <uavcan/debug.hpp> 00013 #include <uavcan/transport/transfer_buffer.hpp> 00014 #include <uavcan/transport/transfer_sender.hpp> 00015 #include <uavcan/marshal/scalar_codec.hpp> 00016 #include <uavcan/marshal/types.hpp> 00017 00018 namespace uavcan 00019 { 00020 00021 class GenericPublisherBase : Noncopyable 00022 { 00023 TransferSender sender_; 00024 MonotonicDuration tx_timeout_; 00025 INode& node_; 00026 00027 protected: 00028 GenericPublisherBase(INode& node, MonotonicDuration tx_timeout, 00029 MonotonicDuration max_transfer_interval) 00030 : sender_(node.getDispatcher(), max_transfer_interval) 00031 , tx_timeout_(tx_timeout) 00032 , node_(node) 00033 { 00034 setTxTimeout(tx_timeout); 00035 #if UAVCAN_DEBUG 00036 UAVCAN_ASSERT(getTxTimeout() == tx_timeout); // Making sure default values are OK 00037 #endif 00038 } 00039 00040 ~GenericPublisherBase() { } 00041 00042 bool isInited() const; 00043 00044 int doInit(DataTypeKind dtkind, const char* dtname, CanTxQueue::Qos qos); 00045 00046 MonotonicTime getTxDeadline() const; 00047 00048 int genericPublish(const StaticTransferBufferImpl& buffer, TransferType transfer_type, 00049 NodeID dst_node_id, TransferID* tid, MonotonicTime blocking_deadline); 00050 00051 TransferSender& getTransferSender() { return sender_; } 00052 const TransferSender& getTransferSender() const { return sender_; } 00053 00054 public: 00055 static MonotonicDuration getMinTxTimeout() { return MonotonicDuration::fromUSec(200); } 00056 static MonotonicDuration getMaxTxTimeout() { return MonotonicDuration::fromMSec(60000); } 00057 00058 MonotonicDuration getTxTimeout() const { return tx_timeout_; } 00059 void setTxTimeout(MonotonicDuration tx_timeout); 00060 00061 /** 00062 * By default, attempt to send a transfer from passive mode will result in an error @ref ErrPassive. 00063 * This option allows to enable sending anonymous transfers from passive mode. 00064 */ 00065 void allowAnonymousTransfers() 00066 { 00067 sender_.allowAnonymousTransfers(); 00068 } 00069 00070 /** 00071 * Priority of outgoing transfers. 00072 */ 00073 TransferPriority getPriority() const { return sender_.getPriority(); } 00074 void setPriority(const TransferPriority prio) { sender_.setPriority(prio); } 00075 00076 INode& getNode() const { return node_; } 00077 }; 00078 00079 /** 00080 * Generic publisher, suitable for messages and services. 00081 * DataSpec - data type specification class 00082 * DataStruct - instantiable class 00083 */ 00084 template <typename DataSpec, typename DataStruct> 00085 class UAVCAN_EXPORT GenericPublisher : public GenericPublisherBase 00086 { 00087 struct ZeroTransferBuffer : public StaticTransferBufferImpl 00088 { 00089 ZeroTransferBuffer() : StaticTransferBufferImpl(UAVCAN_NULLPTR, 0) { } 00090 }; 00091 00092 typedef typename Select<DataStruct::MaxBitLen == 0, 00093 ZeroTransferBuffer, 00094 StaticTransferBuffer<BitLenToByteLen<DataStruct::MaxBitLen>::Result> >::Result Buffer; 00095 00096 enum 00097 { 00098 Qos = (DataTypeKind(DataSpec::DataTypeKind) == DataTypeKindMessage) ? 00099 CanTxQueue::Volatile : CanTxQueue::Persistent 00100 }; 00101 00102 int checkInit(); 00103 00104 int doEncode(const DataStruct& message, ITransferBuffer& buffer) const; 00105 00106 int genericPublish(const DataStruct& message, TransferType transfer_type, NodeID dst_node_id, 00107 TransferID* tid, MonotonicTime blocking_deadline); 00108 00109 public: 00110 /** 00111 * @param max_transfer_interval Maximum expected time interval between subsequent publications. Leave default. 00112 */ 00113 GenericPublisher(INode& node, MonotonicDuration tx_timeout, 00114 MonotonicDuration max_transfer_interval = TransferSender::getDefaultMaxTransferInterval()) 00115 : GenericPublisherBase(node, tx_timeout, max_transfer_interval) 00116 { } 00117 00118 ~GenericPublisher() { } 00119 00120 /** 00121 * Init method can be called prior first publication, but it's not necessary 00122 * because the publisher can be automatically initialized ad-hoc. 00123 */ 00124 int init() 00125 { 00126 return checkInit(); 00127 } 00128 00129 /** 00130 * This overload allows to set the priority; otherwise it's the same. 00131 */ 00132 int init(TransferPriority priority) 00133 { 00134 setPriority(priority); 00135 return checkInit(); 00136 } 00137 00138 int publish(const DataStruct& message, TransferType transfer_type, NodeID dst_node_id, 00139 MonotonicTime blocking_deadline = MonotonicTime()) 00140 { 00141 return genericPublish(message, transfer_type, dst_node_id, UAVCAN_NULLPTR, blocking_deadline); 00142 } 00143 00144 int publish(const DataStruct& message, TransferType transfer_type, NodeID dst_node_id, TransferID tid, 00145 MonotonicTime blocking_deadline = MonotonicTime()) 00146 { 00147 return genericPublish(message, transfer_type, dst_node_id, &tid, blocking_deadline); 00148 } 00149 }; 00150 00151 // ---------------------------------------------------------------------------- 00152 00153 template <typename DataSpec, typename DataStruct> 00154 int GenericPublisher<DataSpec, DataStruct>::checkInit() 00155 { 00156 if (isInited()) 00157 { 00158 return 0; 00159 } 00160 return doInit(DataTypeKind(DataSpec::DataTypeKind), DataSpec::getDataTypeFullName(), CanTxQueue::Qos(Qos)); 00161 } 00162 00163 template <typename DataSpec, typename DataStruct> 00164 int GenericPublisher<DataSpec, DataStruct>::doEncode(const DataStruct& message, ITransferBuffer& buffer) const 00165 { 00166 BitStream bitstream(buffer); 00167 ScalarCodec codec(bitstream); 00168 const int encode_res = DataStruct::encode(message, codec); 00169 if (encode_res <= 0) 00170 { 00171 UAVCAN_ASSERT(0); // Impossible, internal error 00172 return -ErrInvalidMarshalData; 00173 } 00174 return encode_res; 00175 } 00176 00177 template <typename DataSpec, typename DataStruct> 00178 int GenericPublisher<DataSpec, DataStruct>::genericPublish(const DataStruct& message, TransferType transfer_type, 00179 NodeID dst_node_id, TransferID* tid, 00180 MonotonicTime blocking_deadline) 00181 { 00182 const int res = checkInit(); 00183 if (res < 0) 00184 { 00185 return res; 00186 } 00187 00188 Buffer buffer; 00189 00190 const int encode_res = doEncode(message, buffer); 00191 if (encode_res < 0) 00192 { 00193 return encode_res; 00194 } 00195 00196 return GenericPublisherBase::genericPublish(buffer, transfer_type, dst_node_id, tid, blocking_deadline); 00197 } 00198 00199 } 00200 00201 #endif // UAVCAN_NODE_GENERIC_PUBLISHER_HPP_INCLUDED
Generated on Tue Jul 12 2022 17:17:32 by
1.7.2