libuav original
Dependents: UAVCAN UAVCAN_Subscriber
node.hpp
00001 /* 00002 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #ifndef UAVCAN_NODE_NODE_HPP_INCLUDED 00006 #define UAVCAN_NODE_NODE_HPP_INCLUDED 00007 00008 #include <cassert> 00009 #include <uavcan/error.hpp> 00010 #include <uavcan/build_config.hpp> 00011 #include <uavcan/node/abstract_node.hpp> 00012 00013 // High-level functionality available by default 00014 #include <uavcan/protocol/node_status_provider.hpp> 00015 00016 #if !UAVCAN_TINY 00017 # include <uavcan/protocol/data_type_info_provider.hpp> 00018 # include <uavcan/protocol/logger.hpp> 00019 # include <uavcan/protocol/restart_request_server.hpp> 00020 # include <uavcan/protocol/transport_stats_provider.hpp> 00021 #endif 00022 00023 #if !defined(UAVCAN_CPP_VERSION) || !defined(UAVCAN_CPP11) 00024 # error UAVCAN_CPP_VERSION 00025 #endif 00026 00027 namespace uavcan 00028 { 00029 /** 00030 * This is the top-level node API. 00031 * A custom node class can be implemented if needed, in which case it shall inherit INode. 00032 * 00033 * @tparam MemPoolSize Size of memory pool for this node, in bytes. 00034 * Please refer to the documentation for details. 00035 * If this value is zero, the constructor will accept a reference to user-provided allocator. 00036 */ 00037 template <std::size_t MemPoolSize = 0> 00038 class UAVCAN_EXPORT Node : public INode 00039 { 00040 typedef typename 00041 Select<(MemPoolSize > 0), 00042 PoolAllocator<MemPoolSize, MemPoolBlockSize>, // If pool size is specified, use default allocator 00043 IPoolAllocator& // Otherwise use reference to user-provided allocator 00044 >::Result Allocator; 00045 00046 Allocator pool_allocator_; 00047 Scheduler scheduler_; 00048 00049 NodeStatusProvider proto_nsp_; 00050 #if !UAVCAN_TINY 00051 DataTypeInfoProvider proto_dtp_; 00052 Logger proto_logger_; 00053 RestartRequestServer proto_rrs_; 00054 TransportStatsProvider proto_tsp_; 00055 #endif 00056 00057 uint64_t internal_failure_cnt_; 00058 bool started_; 00059 00060 void commonInit() 00061 { 00062 internal_failure_cnt_ = 0; 00063 started_ = false; 00064 } 00065 00066 protected: 00067 virtual void registerInternalFailure(const char* msg) 00068 { 00069 internal_failure_cnt_++; 00070 UAVCAN_TRACE("Node", "Internal failure: %s", msg); 00071 #if UAVCAN_TINY 00072 (void)msg; 00073 #else 00074 (void)getLogger().log(protocol::debug::LogLevel::ERROR, "UAVCAN", msg); 00075 #endif 00076 } 00077 00078 public: 00079 /** 00080 * This overload is only valid if MemPoolSize > 0. 00081 */ 00082 Node(ICanDriver& can_driver, 00083 ISystemClock& system_clock) : 00084 scheduler_(can_driver, pool_allocator_, system_clock), 00085 proto_nsp_(*this) 00086 #if !UAVCAN_TINY 00087 , proto_dtp_(*this) 00088 , proto_logger_(*this) 00089 , proto_rrs_(*this) 00090 , proto_tsp_(*this) 00091 #endif 00092 { 00093 commonInit(); 00094 } 00095 00096 /** 00097 * This overload is only valid if MemPoolSize == 0. 00098 */ 00099 Node(ICanDriver& can_driver, 00100 ISystemClock& system_clock, 00101 IPoolAllocator& allocator) : 00102 pool_allocator_(allocator), 00103 scheduler_(can_driver, pool_allocator_, system_clock), 00104 proto_nsp_(*this) 00105 #if !UAVCAN_TINY 00106 , proto_dtp_(*this) 00107 , proto_logger_(*this) 00108 , proto_rrs_(*this) 00109 , proto_tsp_(*this) 00110 #endif 00111 { 00112 commonInit(); 00113 } 00114 00115 virtual typename RemoveReference<Allocator>::Type& getAllocator() { return pool_allocator_; } 00116 00117 virtual Scheduler& getScheduler() { return scheduler_; } 00118 virtual const Scheduler& getScheduler() const { return scheduler_; } 00119 00120 int spin(MonotonicTime deadline) 00121 { 00122 if (started_) 00123 { 00124 return INode::spin(deadline); 00125 } 00126 return -ErrNotInited; 00127 } 00128 00129 int spin(MonotonicDuration duration) 00130 { 00131 if (started_) 00132 { 00133 return INode::spin(duration); 00134 } 00135 return -ErrNotInited; 00136 } 00137 00138 int spinOnce() 00139 { 00140 if (started_) 00141 { 00142 return INode::spinOnce(); 00143 } 00144 return -ErrNotInited; 00145 } 00146 00147 bool isStarted() const { return started_; } 00148 00149 uint64_t getInternalFailureCount() const { return internal_failure_cnt_; } 00150 00151 /** 00152 * Starts the node and publishes uavcan.protocol.NodeStatus immediately. 00153 * Does not so anything if the node is already started. 00154 * Once started, the node can't stop. 00155 * If the node failed to start up, it's recommended to destroy the current node instance and start over. 00156 * Returns negative error code. 00157 * @param node_status_transfer_priority Transfer priority that will be used for outgoing NodeStatus messages. 00158 * Normal priority is used by default. 00159 */ 00160 int start(const TransferPriority node_status_transfer_priority = TransferPriority::Default); 00161 00162 /** 00163 * Gets/sets the node name, e.g. "com.example.product_name". The node name can be set only once. 00164 * The name must be set before the node is started, otherwise the node will refuse to start up. 00165 */ 00166 const NodeStatusProvider::NodeName& getName() const { return proto_nsp_.getName(); } 00167 void setName(const NodeStatusProvider::NodeName& name) { proto_nsp_.setName(name); } 00168 00169 /** 00170 * Node health code helpers. 00171 */ 00172 void setHealthOk() { proto_nsp_.setHealthOk(); } 00173 void setHealthWarning() { proto_nsp_.setHealthWarning(); } 00174 void setHealthError() { proto_nsp_.setHealthError(); } 00175 void setHealthCritical() { proto_nsp_.setHealthCritical(); } 00176 00177 /** 00178 * Node mode code helpers. 00179 * Note that INITIALIZATION is the default mode; the application has to manually set it to OPERATIONAL. 00180 */ 00181 void setModeOperational() { proto_nsp_.setModeOperational(); } 00182 void setModeInitialization() { proto_nsp_.setModeInitialization(); } 00183 void setModeMaintenance() { proto_nsp_.setModeMaintenance(); } 00184 void setModeSoftwareUpdate() { proto_nsp_.setModeSoftwareUpdate(); } 00185 00186 void setModeOfflineAndPublish() 00187 { 00188 proto_nsp_.setModeOffline(); 00189 (void)proto_nsp_.forcePublish(); 00190 } 00191 00192 /** 00193 * Updates the vendor-specific status code. 00194 */ 00195 void setVendorSpecificStatusCode(NodeStatusProvider::VendorSpecificStatusCode code) 00196 { 00197 proto_nsp_.setVendorSpecificStatusCode(code); 00198 } 00199 00200 /** 00201 * Gets/sets the node version information. 00202 */ 00203 void setSoftwareVersion(const protocol::SoftwareVersion& version) { proto_nsp_.setSoftwareVersion(version); } 00204 void setHardwareVersion(const protocol::HardwareVersion& version) { proto_nsp_.setHardwareVersion(version); } 00205 00206 const protocol::SoftwareVersion& getSoftwareVersion() const { return proto_nsp_.getSoftwareVersion(); } 00207 const protocol::HardwareVersion& getHardwareVersion() const { return proto_nsp_.getHardwareVersion(); } 00208 00209 NodeStatusProvider& getNodeStatusProvider() { return proto_nsp_; } 00210 00211 #if !UAVCAN_TINY 00212 /** 00213 * Restart handler can be installed to handle external node restart requests (highly recommended). 00214 */ 00215 void setRestartRequestHandler(IRestartRequestHandler* handler) { proto_rrs_.setHandler(handler); } 00216 00217 RestartRequestServer& getRestartRequestServer() { return proto_rrs_; } 00218 00219 /** 00220 * Node logging. 00221 * Logging calls are passed directly into the @ref Logger instance. 00222 * Type safe log formatting is supported only in C++11 mode. 00223 * @{ 00224 */ 00225 #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 00226 00227 template <typename... Args> 00228 inline void logDebug(const char* source, const char* format, Args... args) 00229 { 00230 (void)proto_logger_.logDebug(source, format, args...); 00231 } 00232 00233 template <typename... Args> 00234 inline void logInfo(const char* source, const char* format, Args... args) 00235 { 00236 (void)proto_logger_.logInfo(source, format, args...); 00237 } 00238 00239 template <typename... Args> 00240 inline void logWarning(const char* source, const char* format, Args... args) 00241 { 00242 (void)proto_logger_.logWarning(source, format, args...); 00243 } 00244 00245 template <typename... Args> 00246 inline void logError(const char* source, const char* format, Args... args) 00247 { 00248 (void)proto_logger_.logError(source, format, args...); 00249 } 00250 00251 #else 00252 00253 void logDebug(const char* source, const char* text) { (void)proto_logger_.logDebug(source, text); } 00254 void logInfo(const char* source, const char* text) { (void)proto_logger_.logInfo(source, text); } 00255 void logWarning(const char* source, const char* text) { (void)proto_logger_.logWarning(source, text); } 00256 void logError(const char* source, const char* text) { (void)proto_logger_.logError(source, text); } 00257 00258 #endif 00259 /** 00260 * @} 00261 */ 00262 00263 /** 00264 * Use this method to configure logging. 00265 */ 00266 Logger& getLogger() { return proto_logger_; } 00267 00268 #endif // UAVCAN_TINY 00269 }; 00270 00271 // ---------------------------------------------------------------------------- 00272 00273 template <std::size_t MemPoolSize_> 00274 int Node<MemPoolSize_>::start(const TransferPriority priority) 00275 { 00276 if (started_) 00277 { 00278 return 0; 00279 } 00280 GlobalDataTypeRegistry::instance().freeze(); 00281 00282 int res = 0; 00283 res = proto_nsp_.startAndPublish(priority); 00284 if (res < 0) 00285 { 00286 goto fail; 00287 } 00288 #if !UAVCAN_TINY 00289 res = proto_dtp_.start(); 00290 if (res < 0) 00291 { 00292 goto fail; 00293 } 00294 res = proto_logger_.init(); 00295 if (res < 0) 00296 { 00297 goto fail; 00298 } 00299 res = proto_rrs_.start(); 00300 if (res < 0) 00301 { 00302 goto fail; 00303 } 00304 res = proto_tsp_.start(); 00305 if (res < 0) 00306 { 00307 goto fail; 00308 } 00309 #endif 00310 started_ = res >= 0; 00311 return res; 00312 fail: 00313 UAVCAN_ASSERT(res < 0); 00314 return res; 00315 } 00316 00317 } 00318 00319 #endif // UAVCAN_NODE_NODE_HPP_INCLUDED
Generated on Tue Jul 12 2022 17:17:33 by 1.7.2