uc_dynamic_node_id_client.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #include <cstdlib>
7 
8 namespace uavcan
9 {
10 
12 {
13  UAVCAN_TRACE("DynamicNodeIDClient", "Client terminated");
14  stop();
15  dnida_sub_.stop();
16 }
17 
19 {
20  UAVCAN_ASSERT(upper_bound_msec > lower_bound_msec);
21  // coverity[dont_call]
22  return MonotonicDuration::fromMSec(lower_bound_msec +
23  static_cast<uint32_t>(std::rand()) % (upper_bound_msec - lower_bound_msec));
24 }
25 
27 {
28  UAVCAN_ASSERT(mode < NumModes);
30 
31  const MonotonicDuration delay = (mode == ModeWaitingForTimeSlot) ?
32  getRandomDuration(protocol::dynamic_node_id::Allocation::MIN_REQUEST_PERIOD_MS,
33  protocol::dynamic_node_id::Allocation::MAX_REQUEST_PERIOD_MS) :
34  getRandomDuration(protocol::dynamic_node_id::Allocation::MIN_FOLLOWUP_DELAY_MS,
35  protocol::dynamic_node_id::Allocation::MAX_FOLLOWUP_DELAY_MS);
36 
37  startOneShotWithDelay(delay);
38 
39  UAVCAN_TRACE("DynamicNodeIDClient", "Restart mode %d, delay %d ms",
40  static_cast<int>(mode), static_cast<int>(delay.toMSec()));
41 }
42 
44 {
46  UAVCAN_ASSERT(size_of_received_unique_id_ < protocol::dynamic_node_id::Allocation::FieldTypes::unique_id::MaxSize);
47 
49  {
50  UAVCAN_ASSERT(0);
51  terminate();
52  return;
53  }
54 
55  /*
56  * Filling the message.
57  */
58  protocol::dynamic_node_id::Allocation tx;
59  tx.node_id = preferred_node_id_.get();
60  tx.first_part_of_unique_id = (size_of_received_unique_id_ == 0);
61 
62  const uint8_t size_of_unique_id_in_request =
63  min(protocol::dynamic_node_id::Allocation::MAX_LENGTH_OF_UNIQUE_ID_IN_REQUEST,
64  static_cast<uint8_t>(tx.unique_id.capacity() - size_of_received_unique_id_));
65 
66  tx.unique_id.resize(size_of_unique_id_in_request);
68  unique_id_ + size_of_received_unique_id_ + size_of_unique_id_in_request,
69  tx.unique_id.begin());
70 
71  UAVCAN_ASSERT(equal(tx.unique_id.begin(), tx.unique_id.end(), unique_id_ + size_of_received_unique_id_));
72 
73  /*
74  * Resetting the state - this way we can continue with a first stage request on the next attempt.
75  */
78 
79  /*
80  * Broadcasting the message.
81  */
82  UAVCAN_TRACE("DynamicNodeIDClient", "Broadcasting; preferred ID %d, size of UID %d",
83  static_cast<int>(preferred_node_id_.get()),
84  static_cast<int>(tx.unique_id.size()));
85  const int res = dnida_pub_.broadcast(tx);
86  if (res < 0)
87  {
88  dnida_pub_.getNode().registerInternalFailure("DynamicNodeIDClient request failed");
89  }
90 }
91 
93 {
96  {
97  UAVCAN_ASSERT(0);
98  terminate();
99  return;
100  }
101 
102  UAVCAN_TRACE("DynamicNodeIDClient", "Allocation message from %d, %d bytes of unique ID, node ID %d",
103  static_cast<int>(msg.getSrcNodeID().get()), static_cast<int>(msg.unique_id.size()),
104  static_cast<int>(msg.node_id));
105 
106  /*
107  * Switching to passive state by default; will switch to active state if response matches.
108  */
111 
112  /*
113  * Filtering out anonymous and invalid messages.
114  */
115  const bool full_response = (msg.unique_id.size() == msg.unique_id.capacity());
116 
117  if (msg.isAnonymousTransfer() ||
118  msg.unique_id.empty() ||
119  (full_response && (msg.node_id == 0)))
120  {
121  UAVCAN_TRACE("DynamicNodeIDClient", "Message from %d ignored", static_cast<int>(msg.getSrcNodeID().get()));
122  return;
123  }
124 
125  /*
126  * If matches, either switch to active mode or complete the allocation.
127  */
128  if (equal(msg.unique_id.begin(), msg.unique_id.end(), unique_id_))
129  {
130  if (full_response)
131  {
132  allocated_node_id_ = msg.node_id;
134  terminate();
136  UAVCAN_TRACE("DynamicNodeIDClient", "Allocation complete, node ID %d provided by %d",
137  static_cast<int>(allocated_node_id_.get()), static_cast<int>(allocator_node_id_.get()));
138  }
139  else
140  {
141  size_of_received_unique_id_ = msg.unique_id.size();
143  }
144  }
145 }
146 
148  const NodeID preferred_node_id,
149  const TransferPriority transfer_priority)
150 {
151  terminate();
152 
153  // Allocation is not possible if node ID is already set
155  {
156  return -ErrLogic;
157  }
158 
159  // Unique ID initialization & validation
160  copy(unique_id.begin(), unique_id.end(), unique_id_);
161  bool unique_id_is_zero = true;
162  for (uint8_t i = 0; i < sizeof(unique_id_); i++)
163  {
164  if (unique_id_[i] != 0)
165  {
166  unique_id_is_zero = false;
167  break;
168  }
169  }
170 
171  if (unique_id_is_zero)
172  {
173  return -ErrInvalidParam;
174  }
175 
176  if (!preferred_node_id.isValid()) // Only broadcast and unicast are allowed
177  {
178  return -ErrInvalidParam;
179  }
180 
181  // Initializing the fields
182  preferred_node_id_ = preferred_node_id;
188 
189  // Initializing node objects - Rule A
190  int res = dnida_pub_.init();
191  if (res < 0)
192  {
193  return res;
194  }
196  dnida_pub_.setPriority(transfer_priority);
197 
199  if (res < 0)
200  {
201  return res;
202  }
203  dnida_sub_.allowAnonymousTransfers();
204 
206 
207  return 0;
208 }
209 
210 }
uavcan::DynamicNodeIDClient::restartTimer
void restartTimer(const Mode mode)
Definition: uc_dynamic_node_id_client.cpp:26
uavcan::DurationBase::toMSec
int64_t toMSec() const
Definition: time.hpp:44
uavcan::NodeID::isValid
bool isValid() const
Definition: transfer.hpp:134
uavcan::uint32_t
std::uint32_t uint32_t
Definition: std.hpp:26
uavcan::DynamicNodeIDClient::start
int start(const UniqueID &unique_id, const NodeID preferred_node_id=NodeID::Broadcast, const TransferPriority transfer_priority=TransferPriority::OneHigherThanLowest)
Definition: uc_dynamic_node_id_client.cpp:147
uavcan::DynamicNodeIDClient::allocated_node_id_
NodeID allocated_node_id_
Definition: dynamic_node_id_client.hpp:52
uavcan::GenericPublisherBase::getNode
INode & getNode() const
Definition: generic_publisher.hpp:76
uavcan::DynamicNodeIDClient::AllocationCallback
MethodBinder< DynamicNodeIDClient *, void(DynamicNodeIDClient::*)(const ReceivedDataStructure< protocol::dynamic_node_id::Allocation > &)> AllocationCallback
Definition: dynamic_node_id_client.hpp:36
uavcan::DynamicNodeIDClient::Mode
Mode
Definition: dynamic_node_id_client.hpp:38
uavcan::NodeID::get
uint8_t get() const
Definition: transfer.hpp:132
uavcan::DynamicNodeIDClient::allocator_node_id_
NodeID allocator_node_id_
Definition: dynamic_node_id_client.hpp:53
uavcan::NodeID
Definition: transfer.hpp:112
uavcan::DurationBase< MonotonicDuration >::fromMSec
static MonotonicDuration fromMSec(int64_t ms)
Definition: time.hpp:41
uavcan::DynamicNodeIDClient::isAllocationComplete
bool isAllocationComplete() const
Definition: dynamic_node_id_client.hpp:94
uavcan::DynamicNodeIDClient::getRandomDuration
static MonotonicDuration getRandomDuration(uint32_t lower_bound_msec, uint32_t upper_bound_msec)
Definition: uc_dynamic_node_id_client.cpp:18
uavcan::ReceivedDataStructure
Definition: generic_subscriber.hpp:39
UAVCAN_TRACE
#define UAVCAN_TRACE(...)
Definition: libuavcan/libuavcan/include/uavcan/debug.hpp:31
uavcan::MonotonicDuration
Definition: time.hpp:182
uavcan::DynamicNodeIDClient::dnida_sub_
Subscriber< protocol::dynamic_node_id::Allocation, AllocationCallback > dnida_sub_
Definition: dynamic_node_id_client.hpp:46
rand
int rand()
Definition: main.cpp:28
uavcan::DynamicNodeIDClient::ModeWaitingForTimeSlot
@ ModeWaitingForTimeSlot
Definition: dynamic_node_id_client.hpp:40
uavcan::DynamicNodeIDClient::dnida_pub_
Publisher< protocol::dynamic_node_id::Allocation > dnida_pub_
Definition: dynamic_node_id_client.hpp:45
uavcan::GenericPublisherBase::allowAnonymousTransfers
void allowAnonymousTransfers()
Definition: generic_publisher.hpp:65
uavcan::INode::registerInternalFailure
virtual void registerInternalFailure(const char *msg)=0
uavcan_kinetis::ErrLogic
static const uavcan::int16_t ErrLogic
Internal logic error.
Definition: platform_specific_components/kinetis/libuavcan/driver/include/uavcan_kinetis/can.hpp:22
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
uavcan::DynamicNodeIDClient::UniqueID
protocol::HardwareVersion::FieldTypes::unique_id UniqueID
Definition: dynamic_node_id_client.hpp:66
uavcan::DynamicNodeIDClient::size_of_received_unique_id_
uint8_t size_of_received_unique_id_
Definition: dynamic_node_id_client.hpp:49
uavcan::equal
UAVCAN_EXPORT bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
Definition: templates.hpp:324
uavcan::DynamicNodeIDClient::preferred_node_id_
NodeID preferred_node_id_
Definition: dynamic_node_id_client.hpp:51
uavcan::NodeID::isUnicast
bool isUnicast() const
Definition: transfer.hpp:136
uavcan::min
const UAVCAN_EXPORT T & min(const T &a, const T &b)
Definition: templates.hpp:281
uavcan::TransferPriority
Definition: transfer.hpp:28
uavcan::DynamicNodeIDClient::handleAllocation
void handleAllocation(const ReceivedDataStructure< protocol::dynamic_node_id::Allocation > &msg)
Definition: uc_dynamic_node_id_client.cpp:92
dynamic_node_id_client.hpp
uavcan::INode::getNodeID
NodeID getNodeID() const
Definition: abstract_node.hpp:39
uavcan::DynamicNodeIDClient::NumModes
@ NumModes
Definition: dynamic_node_id_client.hpp:42
uavcan::DeadlineHandler::stop
void stop()
Definition: uc_scheduler.cpp:27
uavcan::GenericPublisher::init
int init()
Definition: generic_publisher.hpp:118
uavcan::DynamicNodeIDClient::terminate
void terminate()
Definition: uc_dynamic_node_id_client.cpp:11
uavcan::DynamicNodeIDClient::handleTimerEvent
virtual void handleTimerEvent(const TimerEvent &)
Definition: uc_dynamic_node_id_client.cpp:43
uavcan::Publisher::broadcast
int broadcast(const DataType &message)
Definition: publisher.hpp:52
uavcan::GenericPublisherBase::setPriority
void setPriority(const TransferPriority prio)
Definition: generic_publisher.hpp:74
uavcan
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:204
uavcan::ReceivedDataStructure::getSrcNodeID
NodeID getSrcNodeID() const
Definition: generic_subscriber.hpp:75
uavcan::TimerBase::startOneShotWithDelay
void startOneShotWithDelay(MonotonicDuration delay)
Definition: uc_timer.cpp:35
uavcan::copy
UAVCAN_EXPORT OutputIt copy(InputIt first, InputIt last, OutputIt result)
Definition: templates.hpp:238
uavcan::DynamicNodeIDClient::unique_id_
uint8_t unique_id_[protocol::HardwareVersion::FieldTypes::unique_id::MaxSize]
Definition: dynamic_node_id_client.hpp:48
UAVCAN_ASSERT
#define UAVCAN_ASSERT(x)
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:184
uavcan::TimerEvent
Definition: timer.hpp:32
uavcan::DynamicNodeIDClient::ModeDelayBeforeFollowup
@ ModeDelayBeforeFollowup
Definition: dynamic_node_id_client.hpp:41
uavcan::ReceivedDataStructure::isAnonymousTransfer
bool isAnonymousTransfer() const
Definition: generic_subscriber.hpp:77


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:03