helpers.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
  3. */
  4. #pragma once
  5. #include <uavcan/node/subscriber.hpp>
  6. #include <uavcan/node/timer.hpp>
  7. #include <uavcan/node/service_client.hpp>
  8. #include <uavcan/util/method_binder.hpp>
  9. #include "../node/test_node.hpp"
  10. template <typename DataType>
  11. class SubscriptionCollector : uavcan::Noncopyable
  12. {
  13. void handler(const DataType& msg)
  14. {
  15. this->msg.reset(new DataType(msg));
  16. }
  17. public:
  18. std::auto_ptr<DataType> msg;
  19. typedef uavcan::MethodBinder<SubscriptionCollector*,
  20. void (SubscriptionCollector::*)(const DataType&)> Binder;
  21. Binder bind() { return Binder(this, &SubscriptionCollector::handler); }
  22. };
  23. template <typename DataType>
  24. struct SubscriberWithCollector
  25. {
  26. typedef SubscriptionCollector<DataType> Collector;
  27. typedef uavcan::Subscriber<DataType, typename Collector::Binder> Subscriber;
  28. Collector collector;
  29. Subscriber subscriber;
  30. SubscriberWithCollector(uavcan::INode& node)
  31. : subscriber(node)
  32. { }
  33. int start() { return subscriber.start(collector.bind()); }
  34. };
  35. template <typename DataType>
  36. class ServiceCallResultCollector : uavcan::Noncopyable
  37. {
  38. typedef uavcan::ServiceCallResult<DataType> ServiceCallResult;
  39. public:
  40. class Result
  41. {
  42. const typename ServiceCallResult::Status status_;
  43. uavcan::ServiceCallID call_id_;
  44. typename DataType::Response response_;
  45. public:
  46. Result(typename ServiceCallResult::Status arg_status,
  47. uavcan::ServiceCallID arg_call_id,
  48. const typename DataType::Response& arg_response)
  49. : status_(arg_status)
  50. , call_id_(arg_call_id)
  51. , response_(arg_response)
  52. { }
  53. bool isSuccessful() const { return status_ == ServiceCallResult::Success; }
  54. typename ServiceCallResult::Status getStatus() const { return status_; }
  55. uavcan::ServiceCallID getCallID() const { return call_id_; }
  56. const typename DataType::Response& getResponse() const { return response_; }
  57. typename DataType::Response& getResponse() { return response_; }
  58. };
  59. private:
  60. void handler(const uavcan::ServiceCallResult<DataType>& tmp_result)
  61. {
  62. std::cout << tmp_result << std::endl;
  63. result.reset(new Result(tmp_result.getStatus(), tmp_result.getCallID(), tmp_result.getResponse()));
  64. }
  65. public:
  66. std::auto_ptr<Result> result;
  67. typedef uavcan::MethodBinder<ServiceCallResultCollector*,
  68. void (ServiceCallResultCollector::*)(const uavcan::ServiceCallResult<DataType>&)>
  69. Binder;
  70. Binder bind() { return Binder(this, &ServiceCallResultCollector::handler); }
  71. };
  72. template <typename DataType>
  73. struct ServiceClientWithCollector
  74. {
  75. typedef ServiceCallResultCollector<DataType> Collector;
  76. typedef uavcan::ServiceClient<DataType, typename Collector::Binder> ServiceClient;
  77. Collector collector;
  78. ServiceClient client;
  79. ServiceClientWithCollector(uavcan::INode& node)
  80. : client(node)
  81. { }
  82. int call(uavcan::NodeID node_id, const typename DataType::Request& request)
  83. {
  84. client.setCallback(collector.bind());
  85. return client.call(node_id, request);
  86. }
  87. };
  88. struct BackgroundSpinner : uavcan::TimerBase
  89. {
  90. uavcan::INode& spinning_node;
  91. BackgroundSpinner(uavcan::INode& spinning_node, uavcan::INode& running_node)
  92. : uavcan::TimerBase(running_node)
  93. , spinning_node(spinning_node)
  94. { }
  95. virtual void handleTimerEvent(const uavcan::TimerEvent&)
  96. {
  97. spinning_node.spin(uavcan::MonotonicDuration::fromMSec(1));
  98. }
  99. };
  100. template <typename CanDriver, typename MessageType>
  101. static inline void emulateSingleFrameBroadcastTransfer(CanDriver& can, uavcan::NodeID node_id,
  102. const MessageType& message, uavcan::TransferID tid)
  103. {
  104. uavcan::StaticTransferBuffer<100> buffer;
  105. uavcan::BitStream bitstream(buffer);
  106. uavcan::ScalarCodec codec(bitstream);
  107. // Manual message publication
  108. ASSERT_LT(0, MessageType::encode(message, codec));
  109. ASSERT_GE(8, buffer.getMaxWritePos());
  110. // DataTypeID data_type_id, TransferType transfer_type, NodeID src_node_id, NodeID dst_node_id,
  111. // uint_fast8_t frame_index, TransferID transfer_id, bool last_frame
  112. uavcan::Frame frame(MessageType::DefaultDataTypeID, uavcan::TransferTypeMessageBroadcast,
  113. node_id, uavcan::NodeID::Broadcast, tid);
  114. frame.setStartOfTransfer(true);
  115. frame.setEndOfTransfer(true);
  116. ASSERT_EQ(buffer.getMaxWritePos(), frame.setPayload(buffer.getRawPtr(), buffer.getMaxWritePos()));
  117. uavcan::CanFrame can_frame;
  118. ASSERT_TRUE(frame.compile(can_frame));
  119. can.pushRxToAllIfaces(can_frame);
  120. }