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 <gtest/gtest.h>
7 #include "helpers.hpp"
8 
9 
10 TEST(DynamicNodeIDClient, Basic)
11 {
12  // Node A is Allocator, Node B is Allocatee
14 
15  uavcan::DynamicNodeIDClient dnidac(nodes.b);
16 
19  (void)_reg1;
20 
21  /*
22  * Client initialization
23  */
24  uavcan::protocol::HardwareVersion::FieldTypes::unique_id unique_id;
25 
26  ASSERT_LE(-uavcan::ErrInvalidParam, dnidac.start(unique_id)); // Empty hardware version is not allowed
27 
28  for (uavcan::uint8_t i = 0; i < unique_id.size(); i++)
29  {
30  unique_id[i] = i;
31  }
32 
33  ASSERT_LE(-uavcan::ErrInvalidParam, dnidac.start(unique_id, uavcan::NodeID()));
34 
35  const uavcan::NodeID PreferredNodeID = 42;
36  ASSERT_LE(0, dnidac.start(unique_id, PreferredNodeID));
37 
38  ASSERT_FALSE(dnidac.getAllocatedNodeID().isValid());
39  ASSERT_FALSE(dnidac.getAllocatorNodeID().isValid());
40  ASSERT_FALSE(dnidac.isAllocationComplete());
41 
42  /*
43  * Subscriber (server emulation)
44  */
46  ASSERT_LE(0, dynid_sub.start());
47  dynid_sub.subscriber.allowAnonymousTransfers();
48 
49  /*
50  * Monitoring requests
51  */
53  ASSERT_TRUE(dynid_sub.collector.msg.get());
54  std::cout << "First-stage request:\n" << *dynid_sub.collector.msg << std::endl;
55  ASSERT_EQ(PreferredNodeID.get(), dynid_sub.collector.msg->node_id);
56  ASSERT_TRUE(dynid_sub.collector.msg->first_part_of_unique_id);
57  ASSERT_TRUE(uavcan::equal(dynid_sub.collector.msg->unique_id.begin(),
58  dynid_sub.collector.msg->unique_id.end(),
59  unique_id.begin()));
60  dynid_sub.collector.msg.reset();
61 
62  // Second - rate is no lower than 0.5 Hz
64  ASSERT_TRUE(dynid_sub.collector.msg.get());
65  dynid_sub.collector.msg.reset();
66 
67  ASSERT_FALSE(dnidac.getAllocatedNodeID().isValid());
68  ASSERT_FALSE(dnidac.getAllocatorNodeID().isValid());
69  ASSERT_FALSE(dnidac.isAllocationComplete());
70 
71  /*
72  * Publisher (server emulation)
73  */
75  ASSERT_LE(0, dynid_pub.init());
76 
77  /*
78  * Sending some some Allocation messages - the timer will keep restarting
79  */
80  for (int i = 0; i < 10; i++)
81  {
82  uavcan::protocol::dynamic_node_id::Allocation msg; // Contents of the message doesn't matter
83  ASSERT_LE(0, dynid_pub.broadcast(msg));
85  ASSERT_FALSE(dynid_sub.collector.msg.get());
86  }
87 
88  /*
89  * Responding with partially matching unique ID - the client will respond with second-stage request immediately
90  */
91  const uint8_t BytesPerRequest = uavcan::protocol::dynamic_node_id::Allocation::MAX_LENGTH_OF_UNIQUE_ID_IN_REQUEST;
92  {
93  uavcan::protocol::dynamic_node_id::Allocation msg;
94  msg.unique_id.resize(BytesPerRequest);
95  uavcan::copy(unique_id.begin(), unique_id.begin() + BytesPerRequest, msg.unique_id.begin());
96 
97  std::cout << "First-stage offer:\n" << msg << std::endl;
98 
99  ASSERT_FALSE(dynid_sub.collector.msg.get());
100  ASSERT_LE(0, dynid_pub.broadcast(msg));
102 
103  ASSERT_TRUE(dynid_sub.collector.msg.get());
104  std::cout << "Second-stage request:\n" << *dynid_sub.collector.msg << std::endl;
105  ASSERT_EQ(PreferredNodeID.get(), dynid_sub.collector.msg->node_id);
106  ASSERT_FALSE(dynid_sub.collector.msg->first_part_of_unique_id);
107  ASSERT_TRUE(uavcan::equal(dynid_sub.collector.msg->unique_id.begin(),
108  dynid_sub.collector.msg->unique_id.end(),
109  unique_id.begin() + BytesPerRequest));
110  dynid_sub.collector.msg.reset();
111  }
112 
113  /*
114  * Responding with second-stage offer, expecting the last request back
115  */
116  {
117  uavcan::protocol::dynamic_node_id::Allocation msg;
118  msg.unique_id.resize(BytesPerRequest * 2);
119  uavcan::copy(unique_id.begin(), unique_id.begin() + BytesPerRequest * 2, msg.unique_id.begin());
120 
121  std::cout << "Second-stage offer:\n" << msg << std::endl;
122 
123  ASSERT_FALSE(dynid_sub.collector.msg.get());
124  ASSERT_LE(0, dynid_pub.broadcast(msg));
126 
127  ASSERT_TRUE(dynid_sub.collector.msg.get());
128  std::cout << "Last request:\n" << *dynid_sub.collector.msg << std::endl;
129  ASSERT_EQ(PreferredNodeID.get(), dynid_sub.collector.msg->node_id);
130  ASSERT_FALSE(dynid_sub.collector.msg->first_part_of_unique_id);
131  ASSERT_TRUE(uavcan::equal(dynid_sub.collector.msg->unique_id.begin(),
132  dynid_sub.collector.msg->unique_id.end(),
133  unique_id.begin() + BytesPerRequest * 2));
134  dynid_sub.collector.msg.reset();
135  }
136 
137  ASSERT_FALSE(dnidac.getAllocatedNodeID().isValid());
138  ASSERT_FALSE(dnidac.getAllocatorNodeID().isValid());
139  ASSERT_FALSE(dnidac.isAllocationComplete());
140 
141  /*
142  * Now we have full unique ID for this client received, and it is possible to grant allocation
143  */
144  {
145  uavcan::protocol::dynamic_node_id::Allocation msg;
146  msg.unique_id.resize(16);
147  msg.node_id = 72;
148  uavcan::copy(unique_id.begin(), unique_id.end(), msg.unique_id.begin());
149 
150  ASSERT_FALSE(dynid_sub.collector.msg.get());
151  ASSERT_LE(0, dynid_pub.broadcast(msg));
153  ASSERT_FALSE(dynid_sub.collector.msg.get());
154  }
155 
156  ASSERT_EQ(uavcan::NodeID(72), dnidac.getAllocatedNodeID());
157  ASSERT_EQ(uavcan::NodeID(10), dnidac.getAllocatorNodeID());
158  ASSERT_TRUE(dnidac.isAllocationComplete());
159 }
160 
161 
162 TEST(DynamicNodeIDClient, NonPassiveMode)
163 {
165 
166  uavcan::DynamicNodeIDClient dnidac(nodes.b);
167 
170  (void)_reg1;
171 
172  uavcan::protocol::HardwareVersion::FieldTypes::unique_id unique_id;
173  for (uavcan::uint8_t i = 0; i < unique_id.size(); i++)
174  {
175  unique_id[i] = i;
176  }
177 
178  ASSERT_LE(-uavcan::ErrLogic, dnidac.start(unique_id));
179 }
std::uint8_t uint8_t
Definition: std.hpp:24
UAVCAN_EXPORT bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
Definition: templates.hpp:324
static const NodeID Broadcast
Definition: transfer.hpp:122
UAVCAN_EXPORT OutputIt copy(InputIt first, InputIt last, OutputIt result)
Definition: templates.hpp:238
bool isValid() const
Definition: transfer.hpp:134
static GlobalDataTypeRegistry & instance()
TEST(DynamicNodeIDClient, Basic)
static MonotonicDuration fromMSec(int64_t ms)
Definition: time.hpp:41
int spinBoth(uavcan::MonotonicDuration duration)
Definition: test_node.hpp:176
int start(const UniqueID &unique_id, const NodeID preferred_node_id=NodeID::Broadcast, const TransferPriority transfer_priority=TransferPriority::OneHigherThanLowest)


uavcan_communicator
Author(s):
autogenerated on Wed Jan 11 2023 03:59:39