dynamic_node_id_client.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>
  3. */
  4. #include <gtest/gtest.h>
  5. #include <uavcan/protocol/dynamic_node_id_client.hpp>
  6. #include "helpers.hpp"
  7. TEST(DynamicNodeIDClient, Basic)
  8. {
  9. // Node A is Allocator, Node B is Allocatee
  10. InterlinkedTestNodesWithSysClock nodes(uavcan::NodeID(10), uavcan::NodeID::Broadcast);
  11. uavcan::DynamicNodeIDClient dnidac(nodes.b);
  12. uavcan::GlobalDataTypeRegistry::instance().reset();
  13. uavcan::DefaultDataTypeRegistrator<uavcan::protocol::dynamic_node_id::Allocation> _reg1;
  14. (void)_reg1;
  15. /*
  16. * Client initialization
  17. */
  18. uavcan::protocol::HardwareVersion::FieldTypes::unique_id unique_id;
  19. ASSERT_LE(-uavcan::ErrInvalidParam, dnidac.start(unique_id)); // Empty hardware version is not allowed
  20. for (uavcan::uint8_t i = 0; i < unique_id.size(); i++)
  21. {
  22. unique_id[i] = i;
  23. }
  24. ASSERT_LE(-uavcan::ErrInvalidParam, dnidac.start(unique_id, uavcan::NodeID()));
  25. const uavcan::NodeID PreferredNodeID = 42;
  26. ASSERT_LE(0, dnidac.start(unique_id, PreferredNodeID));
  27. ASSERT_FALSE(dnidac.getAllocatedNodeID().isValid());
  28. ASSERT_FALSE(dnidac.getAllocatorNodeID().isValid());
  29. ASSERT_FALSE(dnidac.isAllocationComplete());
  30. /*
  31. * Subscriber (server emulation)
  32. */
  33. SubscriberWithCollector<uavcan::protocol::dynamic_node_id::Allocation> dynid_sub(nodes.a);
  34. ASSERT_LE(0, dynid_sub.start());
  35. dynid_sub.subscriber.allowAnonymousTransfers();
  36. /*
  37. * Monitoring requests
  38. */
  39. nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(1500));
  40. ASSERT_TRUE(dynid_sub.collector.msg.get());
  41. std::cout << "First-stage request:\n" << *dynid_sub.collector.msg << std::endl;
  42. ASSERT_EQ(PreferredNodeID.get(), dynid_sub.collector.msg->node_id);
  43. ASSERT_TRUE(dynid_sub.collector.msg->first_part_of_unique_id);
  44. ASSERT_TRUE(uavcan::equal(dynid_sub.collector.msg->unique_id.begin(),
  45. dynid_sub.collector.msg->unique_id.end(),
  46. unique_id.begin()));
  47. dynid_sub.collector.msg.reset();
  48. // Second - rate is no lower than 0.5 Hz
  49. nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(1500));
  50. ASSERT_TRUE(dynid_sub.collector.msg.get());
  51. dynid_sub.collector.msg.reset();
  52. ASSERT_FALSE(dnidac.getAllocatedNodeID().isValid());
  53. ASSERT_FALSE(dnidac.getAllocatorNodeID().isValid());
  54. ASSERT_FALSE(dnidac.isAllocationComplete());
  55. /*
  56. * Publisher (server emulation)
  57. */
  58. uavcan::Publisher<uavcan::protocol::dynamic_node_id::Allocation> dynid_pub(nodes.a);
  59. ASSERT_LE(0, dynid_pub.init());
  60. /*
  61. * Sending some some Allocation messages - the timer will keep restarting
  62. */
  63. for (int i = 0; i < 10; i++)
  64. {
  65. uavcan::protocol::dynamic_node_id::Allocation msg; // Contents of the message doesn't matter
  66. ASSERT_LE(0, dynid_pub.broadcast(msg));
  67. nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(210));
  68. ASSERT_FALSE(dynid_sub.collector.msg.get());
  69. }
  70. /*
  71. * Responding with partially matching unique ID - the client will respond with second-stage request immediately
  72. */
  73. const uint8_t BytesPerRequest = uavcan::protocol::dynamic_node_id::Allocation::MAX_LENGTH_OF_UNIQUE_ID_IN_REQUEST;
  74. {
  75. uavcan::protocol::dynamic_node_id::Allocation msg;
  76. msg.unique_id.resize(BytesPerRequest);
  77. uavcan::copy(unique_id.begin(), unique_id.begin() + BytesPerRequest, msg.unique_id.begin());
  78. std::cout << "First-stage offer:\n" << msg << std::endl;
  79. ASSERT_FALSE(dynid_sub.collector.msg.get());
  80. ASSERT_LE(0, dynid_pub.broadcast(msg));
  81. nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(500));
  82. ASSERT_TRUE(dynid_sub.collector.msg.get());
  83. std::cout << "Second-stage request:\n" << *dynid_sub.collector.msg << std::endl;
  84. ASSERT_EQ(PreferredNodeID.get(), dynid_sub.collector.msg->node_id);
  85. ASSERT_FALSE(dynid_sub.collector.msg->first_part_of_unique_id);
  86. ASSERT_TRUE(uavcan::equal(dynid_sub.collector.msg->unique_id.begin(),
  87. dynid_sub.collector.msg->unique_id.end(),
  88. unique_id.begin() + BytesPerRequest));
  89. dynid_sub.collector.msg.reset();
  90. }
  91. /*
  92. * Responding with second-stage offer, expecting the last request back
  93. */
  94. {
  95. uavcan::protocol::dynamic_node_id::Allocation msg;
  96. msg.unique_id.resize(BytesPerRequest * 2);
  97. uavcan::copy(unique_id.begin(), unique_id.begin() + BytesPerRequest * 2, msg.unique_id.begin());
  98. std::cout << "Second-stage offer:\n" << msg << std::endl;
  99. ASSERT_FALSE(dynid_sub.collector.msg.get());
  100. ASSERT_LE(0, dynid_pub.broadcast(msg));
  101. nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(500));
  102. ASSERT_TRUE(dynid_sub.collector.msg.get());
  103. std::cout << "Last request:\n" << *dynid_sub.collector.msg << std::endl;
  104. ASSERT_EQ(PreferredNodeID.get(), dynid_sub.collector.msg->node_id);
  105. ASSERT_FALSE(dynid_sub.collector.msg->first_part_of_unique_id);
  106. ASSERT_TRUE(uavcan::equal(dynid_sub.collector.msg->unique_id.begin(),
  107. dynid_sub.collector.msg->unique_id.end(),
  108. unique_id.begin() + BytesPerRequest * 2));
  109. dynid_sub.collector.msg.reset();
  110. }
  111. ASSERT_FALSE(dnidac.getAllocatedNodeID().isValid());
  112. ASSERT_FALSE(dnidac.getAllocatorNodeID().isValid());
  113. ASSERT_FALSE(dnidac.isAllocationComplete());
  114. /*
  115. * Now we have full unique ID for this client received, and it is possible to grant allocation
  116. */
  117. {
  118. uavcan::protocol::dynamic_node_id::Allocation msg;
  119. msg.unique_id.resize(16);
  120. msg.node_id = 72;
  121. uavcan::copy(unique_id.begin(), unique_id.end(), msg.unique_id.begin());
  122. ASSERT_FALSE(dynid_sub.collector.msg.get());
  123. ASSERT_LE(0, dynid_pub.broadcast(msg));
  124. nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(2000));
  125. ASSERT_FALSE(dynid_sub.collector.msg.get());
  126. }
  127. ASSERT_EQ(uavcan::NodeID(72), dnidac.getAllocatedNodeID());
  128. ASSERT_EQ(uavcan::NodeID(10), dnidac.getAllocatorNodeID());
  129. ASSERT_TRUE(dnidac.isAllocationComplete());
  130. }
  131. TEST(DynamicNodeIDClient, NonPassiveMode)
  132. {
  133. InterlinkedTestNodesWithSysClock nodes;
  134. uavcan::DynamicNodeIDClient dnidac(nodes.b);
  135. uavcan::GlobalDataTypeRegistry::instance().reset();
  136. uavcan::DefaultDataTypeRegistrator<uavcan::protocol::dynamic_node_id::Allocation> _reg1;
  137. (void)_reg1;
  138. uavcan::protocol::HardwareVersion::FieldTypes::unique_id unique_id;
  139. for (uavcan::uint8_t i = 0; i < unique_id.size(); i++)
  140. {
  141. unique_id[i] = i;
  142. }
  143. ASSERT_LE(-uavcan::ErrLogic, dnidac.start(unique_id));
  144. }