/* * Copyright (C) 2014 Pavel Kirienko */ #ifndef UAVCAN_PROTOCOL_NODE_STATUS_PROVIDER_HPP_INCLUDED #define UAVCAN_PROTOCOL_NODE_STATUS_PROVIDER_HPP_INCLUDED #include #include #include #include #include #include #include #include namespace uavcan { /** * This optional interface can be implemented by the user in order to update the node status as necessary, * immediately before the next NodeStatus message is emitted by @ref NodeStatusProvider. */ class IAdHocNodeStatusUpdater { public: /** * This method is invoked by the library from @ref NodeStatusProvider from the library's thread immediately * before the next NodeStatus message is transmitted. The application can implement this method to perform * node status updates only as necessary. * The application is expected to invoke the methods of @ref NodeStatusProvider to update the status * from this method. * Note that this method is only invoked when publication is happening by the timer event. * It will NOT be invoked if the following methods are used to trigger node status publication: * - @ref NodeStatusProvider::startAndPublish() * - @ref NodeStatusProvider::forcePublish() */ virtual void updateNodeStatus() = 0; virtual ~IAdHocNodeStatusUpdater() { } }; /** * Provides the status and basic information about this node to other network participants. * * Usually the application does not need to deal with this class directly - it's instantiated by the node class. * * Default values: * - health - OK * - mode - INITIALIZATION */ class UAVCAN_EXPORT NodeStatusProvider : private TimerBase { typedef MethodBinder GetNodeInfoCallback; const MonotonicTime creation_timestamp_; Publisher node_status_pub_; ServiceServer gni_srv_; protocol::GetNodeInfo::Response node_info_; IAdHocNodeStatusUpdater* ad_hoc_status_updater_; INode& getNode() { return node_status_pub_.getNode(); } bool isNodeInfoInitialized() const; int publish(); virtual void handleTimerEvent(const TimerEvent&); void handleGetNodeInfoRequest(const protocol::GetNodeInfo::Request&, protocol::GetNodeInfo::Response& rsp); public: typedef typename StorageType::Type VendorSpecificStatusCode; typedef typename StorageType::Type NodeName; explicit NodeStatusProvider(INode& node) : TimerBase(node) , creation_timestamp_(node.getMonotonicTime()) , node_status_pub_(node) , gni_srv_(node) , ad_hoc_status_updater_(UAVCAN_NULLPTR) { UAVCAN_ASSERT(!creation_timestamp_.isZero()); node_info_.status.mode = protocol::NodeStatus::MODE_INITIALIZATION; node_info_.status.health = protocol::NodeStatus::HEALTH_OK; } /** * Starts the provider and immediately broadcasts uavcan.protocol.NodeStatus. * Returns negative error code. */ int startAndPublish(const TransferPriority priority = TransferPriority::Default); /** * Publish the message uavcan.protocol.NodeStatus right now, out of schedule. * Returns negative error code. */ int forcePublish() { return publish(); } /** * Allows to override default publishing rate for uavcan.protocol.NodeStatus. * Refer to the DSDL definition of uavcan.protocol.NodeStatus to see what is the default rate. * Doesn't fail; if the value is outside of acceptable range, a closest valid value will be used instead. */ void setStatusPublicationPeriod(uavcan::MonotonicDuration period); uavcan::MonotonicDuration getStatusPublicationPeriod() const; /** * Configure the optional handler that is invoked before every node status message is emitted. * By default no handler is installed. * It is allowed to pass a null pointer, that will disable the ad-hoc update feature. * @ref IAdHocNodeStatusUpdater */ void setAdHocNodeStatusUpdater(IAdHocNodeStatusUpdater* updater); IAdHocNodeStatusUpdater* getAdHocNodeStatusUpdater() const { return ad_hoc_status_updater_; } /** * Local node health code control. */ uint8_t getHealth() const { return node_info_.status.health; } void setHealth(uint8_t code); void setHealthOk() { setHealth(protocol::NodeStatus::HEALTH_OK); } void setHealthWarning() { setHealth(protocol::NodeStatus::HEALTH_WARNING); } void setHealthError() { setHealth(protocol::NodeStatus::HEALTH_ERROR); } void setHealthCritical() { setHealth(protocol::NodeStatus::HEALTH_CRITICAL); } /** * Local node mode code control. */ uint8_t getMode() const { return node_info_.status.mode; } void setMode(uint8_t code); void setModeOperational() { setMode(protocol::NodeStatus::MODE_OPERATIONAL); } void setModeInitialization() { setMode(protocol::NodeStatus::MODE_INITIALIZATION); } void setModeMaintenance() { setMode(protocol::NodeStatus::MODE_MAINTENANCE); } void setModeSoftwareUpdate() { setMode(protocol::NodeStatus::MODE_SOFTWARE_UPDATE); } void setModeOffline() { setMode(protocol::NodeStatus::MODE_OFFLINE); } /** * Local node vendor-specific status code control. */ void setVendorSpecificStatusCode(VendorSpecificStatusCode code); VendorSpecificStatusCode getVendorSpecificStatusCode() const { return node_info_.status.vendor_specific_status_code; } /** * Local node name control. * Can be set only once before the provider is started. * The provider will refuse to start if the node name is not set. */ const NodeName& getName() const { return node_info_.name; } void setName(const NodeName& name); /** * Node version information. * Can be set only once before the provider is started. */ const protocol::SoftwareVersion& getSoftwareVersion() const { return node_info_.software_version; } const protocol::HardwareVersion& getHardwareVersion() const { return node_info_.hardware_version; } void setSoftwareVersion(const protocol::SoftwareVersion& version); void setHardwareVersion(const protocol::HardwareVersion& version); }; } #endif // UAVCAN_PROTOCOL_NODE_STATUS_PROVIDER_HPP_INCLUDED