Руслан Урядинский / libuavcan

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers node_status_provider.hpp Source File

node_status_provider.hpp

00001 /*
00002  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #ifndef UAVCAN_PROTOCOL_NODE_STATUS_PROVIDER_HPP_INCLUDED
00006 #define UAVCAN_PROTOCOL_NODE_STATUS_PROVIDER_HPP_INCLUDED
00007 
00008 #include <uavcan/node/publisher.hpp>
00009 #include <uavcan/node/subscriber.hpp>
00010 #include <uavcan/node/service_server.hpp>
00011 #include <uavcan/node/timer.hpp>
00012 #include <uavcan/util/method_binder.hpp>
00013 #include <uavcan/build_config.hpp>
00014 #include <uavcan/protocol/NodeStatus.hpp>
00015 #include <uavcan/protocol/GetNodeInfo.hpp>
00016 
00017 namespace uavcan
00018 {
00019 /**
00020  * This optional interface can be implemented by the user in order to update the node status as necessary,
00021  * immediately before the next NodeStatus message is emitted by @ref NodeStatusProvider.
00022  */
00023 class IAdHocNodeStatusUpdater
00024 {
00025 public:
00026     /**
00027      * This method is invoked by the library from @ref NodeStatusProvider from the library's thread immediately
00028      * before the next NodeStatus message is transmitted. The application can implement this method to perform
00029      * node status updates only as necessary.
00030      * The application is expected to invoke the methods of @ref NodeStatusProvider to update the status
00031      * from this method.
00032      * Note that this method is only invoked when publication is happening by the timer event.
00033      * It will NOT be invoked if the following methods are used to trigger node status publication:
00034      *  - @ref NodeStatusProvider::startAndPublish()
00035      *  - @ref NodeStatusProvider::forcePublish()
00036      */
00037     virtual void updateNodeStatus() = 0;
00038 
00039     virtual ~IAdHocNodeStatusUpdater() { }
00040 };
00041 
00042 /**
00043  * Provides the status and basic information about this node to other network participants.
00044  *
00045  * Usually the application does not need to deal with this class directly - it's instantiated by the node class.
00046  *
00047  * Default values:
00048  *  - health - OK
00049  *  - mode   - INITIALIZATION
00050  */
00051 class UAVCAN_EXPORT NodeStatusProvider : private TimerBase
00052 {
00053     typedef MethodBinder<NodeStatusProvider*,
00054                          void (NodeStatusProvider::*)(const protocol::GetNodeInfo::Request&,
00055                                                       protocol::GetNodeInfo::Response&)> GetNodeInfoCallback;
00056 
00057     const MonotonicTime creation_timestamp_;
00058 
00059     Publisher<protocol::NodeStatus>  node_status_pub_;
00060     ServiceServer<protocol::GetNodeInfo, GetNodeInfoCallback> gni_srv_;
00061 
00062     protocol::GetNodeInfo::Response node_info_;
00063 
00064     IAdHocNodeStatusUpdater* ad_hoc_status_updater_;
00065 
00066     INode& getNode() { return node_status_pub_.getNode(); }
00067 
00068     bool isNodeInfoInitialized() const;
00069 
00070     int publish();
00071 
00072     virtual void handleTimerEvent(const TimerEvent&);
00073     void handleGetNodeInfoRequest(const protocol::GetNodeInfo::Request&, protocol::GetNodeInfo::Response& rsp);
00074 
00075 public:
00076     typedef typename StorageType<typename protocol::NodeStatus::FieldTypes::vendor_specific_status_code>::Type
00077         VendorSpecificStatusCode;
00078 
00079     typedef typename StorageType<typename protocol::GetNodeInfo::Response::FieldTypes::name>::Type NodeName;
00080 
00081     explicit NodeStatusProvider(INode& node)
00082         : TimerBase(node)
00083         , creation_timestamp_(node.getMonotonicTime())
00084         , node_status_pub_(node)
00085         , gni_srv_(node)
00086         , ad_hoc_status_updater_(UAVCAN_NULLPTR)
00087     {
00088         UAVCAN_ASSERT(!creation_timestamp_.isZero());
00089 
00090         node_info_.status.mode = protocol::NodeStatus::MODE_INITIALIZATION;
00091 
00092         node_info_.status.health = protocol::NodeStatus::HEALTH_OK;
00093     }
00094 
00095     /**
00096      * Starts the provider and immediately broadcasts uavcan.protocol.NodeStatus.
00097      * Returns negative error code.
00098      */
00099     int startAndPublish(const TransferPriority priority = TransferPriority::Default);
00100 
00101     /**
00102      * Publish the message uavcan.protocol.NodeStatus right now, out of schedule.
00103      * Returns negative error code.
00104      */
00105     int forcePublish() { return publish(); }
00106 
00107     /**
00108      * Allows to override default publishing rate for uavcan.protocol.NodeStatus.
00109      * Refer to the DSDL definition of uavcan.protocol.NodeStatus to see what is the default rate.
00110      * Doesn't fail; if the value is outside of acceptable range, a closest valid value will be used instead.
00111      */
00112     void setStatusPublicationPeriod(uavcan::MonotonicDuration period);
00113     uavcan::MonotonicDuration getStatusPublicationPeriod() const;
00114 
00115     /**
00116      * Configure the optional handler that is invoked before every node status message is emitted.
00117      * By default no handler is installed.
00118      * It is allowed to pass a null pointer, that will disable the ad-hoc update feature.
00119      * @ref IAdHocNodeStatusUpdater
00120      */
00121     void setAdHocNodeStatusUpdater(IAdHocNodeStatusUpdater* updater);
00122     IAdHocNodeStatusUpdater* getAdHocNodeStatusUpdater() const { return ad_hoc_status_updater_; }
00123 
00124     /**
00125      * Local node health code control.
00126      */
00127     uint8_t getHealth() const { return node_info_.status.health; }
00128     void setHealth(uint8_t code);
00129     void setHealthOk()           { setHealth(protocol::NodeStatus::HEALTH_OK); }
00130     void setHealthWarning()      { setHealth(protocol::NodeStatus::HEALTH_WARNING); }
00131     void setHealthError()        { setHealth(protocol::NodeStatus::HEALTH_ERROR); }
00132     void setHealthCritical()     { setHealth(protocol::NodeStatus::HEALTH_CRITICAL); }
00133 
00134     /**
00135      * Local node mode code control.
00136      */
00137     uint8_t getMode() const { return node_info_.status.mode; }
00138     void setMode(uint8_t code);
00139     void setModeOperational()    { setMode(protocol::NodeStatus::MODE_OPERATIONAL); }
00140     void setModeInitialization() { setMode(protocol::NodeStatus::MODE_INITIALIZATION); }
00141     void setModeMaintenance()    { setMode(protocol::NodeStatus::MODE_MAINTENANCE); }
00142     void setModeSoftwareUpdate() { setMode(protocol::NodeStatus::MODE_SOFTWARE_UPDATE); }
00143     void setModeOffline()        { setMode(protocol::NodeStatus::MODE_OFFLINE); }
00144 
00145     /**
00146      * Local node vendor-specific status code control.
00147      */
00148     void setVendorSpecificStatusCode(VendorSpecificStatusCode code);
00149     VendorSpecificStatusCode getVendorSpecificStatusCode() const
00150     {
00151         return node_info_.status.vendor_specific_status_code;
00152     }
00153 
00154     /**
00155      * Local node name control.
00156      * Can be set only once before the provider is started.
00157      * The provider will refuse to start if the node name is not set.
00158      */
00159     const NodeName& getName() const { return node_info_.name; }
00160     void setName(const NodeName& name);
00161 
00162     /**
00163      * Node version information.
00164      * Can be set only once before the provider is started.
00165      */
00166     const protocol::SoftwareVersion& getSoftwareVersion() const { return node_info_.software_version; }
00167     const protocol::HardwareVersion& getHardwareVersion() const { return node_info_.hardware_version; }
00168     void setSoftwareVersion(const protocol::SoftwareVersion& version);
00169     void setHardwareVersion(const protocol::HardwareVersion& version);
00170 };
00171 
00172 }
00173 
00174 #endif // UAVCAN_PROTOCOL_NODE_STATUS_PROVIDER_HPP_INCLUDED