Skip to content

Commit

Permalink
Added IAdHocNodeStatusUpdater
Browse files Browse the repository at this point in the history
  • Loading branch information
pavel-kirienko committed Jan 2, 2018
1 parent 0066382 commit da34eae
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 0 deletions.
35 changes: 35 additions & 0 deletions libuavcan/include/uavcan/protocol/node_status_provider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,29 @@

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.
*
Expand All @@ -38,6 +61,8 @@ class UAVCAN_EXPORT NodeStatusProvider : private TimerBase

protocol::GetNodeInfo::Response node_info_;

IAdHocNodeStatusUpdater* ad_hoc_status_updater_;

INode& getNode() { return node_status_pub_.getNode(); }

bool isNodeInfoInitialized() const;
Expand All @@ -58,6 +83,7 @@ class UAVCAN_EXPORT NodeStatusProvider : private TimerBase
, creation_timestamp_(node.getMonotonicTime())
, node_status_pub_(node)
, gni_srv_(node)
, ad_hoc_status_updater_(UAVCAN_NULLPTR)
{
UAVCAN_ASSERT(!creation_timestamp_.isZero());

Expand Down Expand Up @@ -86,6 +112,15 @@ class UAVCAN_EXPORT NodeStatusProvider : private TimerBase
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.
*/
Expand Down
10 changes: 10 additions & 0 deletions libuavcan/src/protocol/uc_node_status_provider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ void NodeStatusProvider::handleTimerEvent(const TimerEvent&)
}
else
{
if (ad_hoc_status_updater_ != UAVCAN_NULLPTR)
{
ad_hoc_status_updater_->updateNodeStatus();
}

const int res = publish();
if (res < 0)
{
Expand Down Expand Up @@ -109,6 +114,11 @@ uavcan::MonotonicDuration NodeStatusProvider::getStatusPublicationPeriod() const
return TimerBase::getPeriod();
}

void NodeStatusProvider::setAdHocNodeStatusUpdater(IAdHocNodeStatusUpdater* updater)
{
ad_hoc_status_updater_ = updater; // Can be nullptr, that's okay
}

void NodeStatusProvider::setHealth(uint8_t code)
{
node_info_.status.health = code;
Expand Down
34 changes: 34 additions & 0 deletions libuavcan/test/protocol/node_status_provider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@
#include "helpers.hpp"


struct AdHocNodeStatusUpdater : public uavcan::IAdHocNodeStatusUpdater
{
uavcan::uint64_t invokations;

AdHocNodeStatusUpdater() : invokations(0) { }

virtual void updateNodeStatus()
{
invokations++;
}
};


TEST(NodeStatusProvider, Basic)
{
InterlinkedTestNodesWithSysClock nodes;
Expand Down Expand Up @@ -60,6 +73,11 @@ TEST(NodeStatusProvider, Basic)
ASSERT_EQ(uavcan::MonotonicDuration::fromMSec(uavcan::protocol::NodeStatus::MAX_BROADCASTING_PERIOD_MS),
nsp.getStatusPublicationPeriod());

AdHocNodeStatusUpdater ad_hoc;
ASSERT_EQ(UAVCAN_NULLPTR, nsp.getAdHocNodeStatusUpdater());
nsp.setAdHocNodeStatusUpdater(&ad_hoc);
ASSERT_EQ(&ad_hoc, nsp.getAdHocNodeStatusUpdater());

/*
* Initial status publication
*/
Expand All @@ -75,6 +93,8 @@ TEST(NodeStatusProvider, Basic)
ASSERT_EQ(0, status_sub.collector.msg->vendor_specific_status_code);
ASSERT_GE(1, status_sub.collector.msg->uptime_sec);

ASSERT_EQ(0, ad_hoc.invokations); // Not invoked from startAndPublish()

/*
* Altering the vendor-specific status code, forcePublish()-ing it and checking the result
*/
Expand All @@ -90,6 +110,8 @@ TEST(NodeStatusProvider, Basic)
ASSERT_EQ(1234, status_sub.collector.msg->vendor_specific_status_code);
ASSERT_GE(1, status_sub.collector.msg->uptime_sec);

ASSERT_EQ(0, ad_hoc.invokations); // Not invoked from forcePublish()

/*
* Explicit node info request
*/
Expand All @@ -113,4 +135,16 @@ TEST(NodeStatusProvider, Basic)
ASSERT_TRUE(swver == gni_cln.collector.result->getResponse().software_version);

ASSERT_EQ("superluminal_communication_unit", gni_cln.collector.result->getResponse().name);

ASSERT_EQ(0, ad_hoc.invokations); // No timer-triggered publications happened yet

/*
* Timer triggered publication
*/
EXPECT_EQ(3, nodes.a.getDispatcher().getTransferPerfCounter().getTxTransferCount());

nodes.spinBoth(nsp.getStatusPublicationPeriod());

EXPECT_EQ(1, ad_hoc.invokations); // No timer-triggered publications happened yet
EXPECT_EQ(4, nodes.a.getDispatcher().getTransferPerfCounter().getTxTransferCount());
}

0 comments on commit da34eae

Please sign in to comment.