Руслан Урядинский / libuavcan

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dynamic_node_id_client.hpp Source File

dynamic_node_id_client.hpp

00001 /*
00002  * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #ifndef UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_CLIENT_HPP_INCLUDED
00006 #define UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_CLIENT_HPP_INCLUDED
00007 
00008 #include <uavcan/node/subscriber.hpp>
00009 #include <uavcan/node/publisher.hpp>
00010 #include <uavcan/node/timer.hpp>
00011 #include <uavcan/util/method_binder.hpp>
00012 #include <uavcan/build_config.hpp>
00013 #include <uavcan/protocol/dynamic_node_id/Allocation.hpp>
00014 #include <uavcan/protocol/HardwareVersion.hpp>
00015 
00016 namespace uavcan
00017 {
00018 /**
00019  * This class implements client-side logic of dynamic node ID allocation procedure.
00020  *
00021  * Once started, the object will be publishing dynamic node ID allocation requests at the default frequency defined
00022  * by the specification, until a Node ID is granted by the allocator.
00023  *
00024  * If the local node is equipped with redundant CAN interfaces, all of them will be used for publishing requests
00025  * and listening for responses.
00026  *
00027  * Once dynamic allocation is complete (or not needed anymore), the object can be deleted.
00028  *
00029  * Note that this class uses std::rand(), which must be correctly seeded before use.
00030  */
00031 class UAVCAN_EXPORT DynamicNodeIDClient : private TimerBase
00032 {
00033     typedef MethodBinder<DynamicNodeIDClient*,
00034                          void (DynamicNodeIDClient::*)
00035                              (const ReceivedDataStructure<protocol::dynamic_node_id::Allocation>&)>
00036         AllocationCallback;
00037 
00038     enum Mode
00039     {
00040         ModeWaitingForTimeSlot,
00041         ModeDelayBeforeFollowup,
00042         NumModes
00043     };
00044 
00045     Publisher<protocol::dynamic_node_id::Allocation>  dnida_pub_;
00046     Subscriber<protocol::dynamic_node_id::Allocation, AllocationCallback> dnida_sub_;
00047 
00048     uint8_t unique_id_[protocol::HardwareVersion::FieldTypes::unique_id::MaxSize];
00049     uint8_t size_of_received_unique_id_;
00050 
00051     NodeID preferred_node_id_;
00052     NodeID allocated_node_id_;
00053     NodeID allocator_node_id_;
00054 
00055     void terminate();
00056 
00057     static MonotonicDuration getRandomDuration(uint32_t lower_bound_msec, uint32_t upper_bound_msec);
00058 
00059     void restartTimer(const Mode mode);
00060 
00061     virtual void handleTimerEvent(const TimerEvent&);
00062 
00063     void handleAllocation(const ReceivedDataStructure<protocol::dynamic_node_id::Allocation>& msg);
00064 
00065 public:
00066     typedef protocol::HardwareVersion::FieldTypes::unique_id UniqueID;
00067 
00068     DynamicNodeIDClient(INode& node)
00069         : TimerBase(node)
00070         , dnida_pub_(node)
00071         , dnida_sub_(node)
00072         , size_of_received_unique_id_(0)
00073     { }
00074 
00075     /**
00076      * @param unique_id         Unique ID of the local node. Must be the same as in the hardware version struct.
00077      * @param preferred_node_id Node ID that the application would like to take; set to broadcast (zero) if
00078      *                          the application doesn't have any preference (this is default).
00079      * @param transfer_priority Transfer priority, Normal by default.
00080      * @return                  Zero on success
00081      *                          Negative error code on failure
00082      *                          -ErrLogic if 1. the node is not in passive mode or 2. the client is already started
00083      */
00084     int start(const UniqueID& unique_id,
00085               const NodeID preferred_node_id = NodeID::Broadcast,
00086               const TransferPriority transfer_priority = TransferPriority::OneHigherThanLowest);
00087 
00088     /**
00089      * Use this method to determine when allocation is complete.
00090      */
00091     bool isAllocationComplete() const { return getAllocatedNodeID().isUnicast(); }
00092 
00093     /**
00094      * This method allows to retrieve the node ID that was allocated to the local node.
00095      * If no node ID was allocated yet, the returned node ID will be invalid (non-unicast).
00096      * @return          If allocation is complete, a valid unicast node ID will be returned.
00097      *                  If allocation is not complete yet, a non-unicast node ID will be returned.
00098      */
00099     NodeID getAllocatedNodeID() const { return allocated_node_id_; }
00100 
00101     /**
00102      * This method allows to retrieve node ID of the allocator that granted our Node ID.
00103      * If no node ID was allocated yet, the returned node ID will be invalid (non-unicast).
00104      * @return          If allocation is complete, a valid unicast node ID will be returned.
00105      *                  If allocation is not complete yet, an non-unicast node ID will be returned.
00106      */
00107     NodeID getAllocatorNodeID() const { return allocator_node_id_; }
00108 };
00109 
00110 }
00111 
00112 #endif // UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_CLIENT_HPP_INCLUDED