MIRA
CANOpenNMTMaster.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 MetraLabs GmbH (MLAB), GERMANY.
3  * All rights reserved.
4  * Contact: info@MetraLabs.com
5  *
6  * Commercial Usage:
7  * Licensees holding valid commercial licenses may use this file in
8  * accordance with the commercial license agreement provided with the
9  * software or, alternatively, in accordance with the terms contained in
10  * a written agreement between you and MetraLabs.
11  *
12  * GNU General Public License Usage:
13  * Alternatively, this file may be used under the terms of the GNU
14  * General Public License version 3.0 as published by the Free Software
15  * Foundation and appearing in the file LICENSE.GPL3 included in the
16  * packaging of this file. Please review the following information to
17  * ensure the GNU General Public License version 3.0 requirements will be
18  * met: http://www.gnu.org/copyleft/gpl.html.
19  * Alternatively you may (at your option) use any later version of the GNU
20  * General Public License if such license has been publicly approved by
21  * MetraLabs (or its successors, if any).
22  *
23  * IN NO EVENT SHALL "MLAB" BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
24  * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE
25  * OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLABS" HAS BEEN
26  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * "MLAB" SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
31  * "AS IS" BASIS, AND "MLAB" HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
32  * SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
33  */
34 
43 #ifndef _MLAB_CANOPENNMTMASTER_H_
44 #define _MLAB_CANOPENNMTMASTER_H_
45 
46 #include <queue>
47 
48 #ifndef Q_MOC_RUN
49 #include <boost/thread/future.hpp>
50 #endif
51 
52 #include <can/CANInterface.h>
53 #include <can/CANOpenDefs.h>
54 
55 namespace mira { namespace can {
56 
58 
60 typedef boost::function<void (uint8, CANOpenNodeStatus)> CANOpenHeartbeat;
61 
63 
64 class CANOpenNMTMaster;
65 
67 
72 {
73 public:
74 
76  CANOpenNodeStatusFuture() : mNMTMaster(NULL), mRequestID(0) {}
77 
79  CANOpenNodeStatusFuture(boost::unique_future<CANOpenNodeStatus> other,
80  CANOpenNMTMaster* master, uint64 requestID) :
81  mNMTMaster(master), mRequestID(requestID)
82  {
83  this->mFuture.swap(other);
84  }
85 
88  this->swap(other);
89  }
90 
93  this->swap(other);
94  return *this;
95  }
96 
99 
100 public:
101  // delegate to boost future
102 
104  bool isReady() const { return mFuture.is_ready(); }
105 
110  bool hasException() const { return mFuture.has_exception(); }
111 
116  bool hasValue() const { return mFuture.has_value(); }
117 
123  void wait() const { mFuture.wait(); }
124 
131  template<typename Duration>
132  bool timedWait(Duration const& relTime) const {
133  return mFuture.timed_wait(relTime);
134  }
135 
142  bool timedWaitUntil(boost::system_time const& absTime) const {
143  return mFuture.timed_wait_until(absTime);
144  }
145 
148  mFuture.swap(other.mFuture);
149  std::swap(mNMTMaster, other.mNMTMaster);
150  std::swap(mRequestID, other.mRequestID);
151  }
152 
160  CANOpenNodeStatus get() { return mFuture.get(); }
161 
162 protected:
164  uint64 mRequestID;
165  boost::unique_future<CANOpenNodeStatus> mFuture;
166 };
167 
169 
174 {
176 
177 public:
180 
186 
188  virtual ~CANOpenNMTMaster();
189 
191 
192 public:
195 
201  uint32 addHeartbeatCallback(CANOpenHeartbeat iCallback);
202 
207  void removeHeartbeatCallback(uint32 pFuncID);
208 
210 
211 public:
214 
220  void startNode(uint8 iNodeID);
221 
227  void stopNode(uint8 iNodeID);
228 
234  void preOperationalNode(uint8 iNodeID);
235 
241  void resetNode(uint8 iNodeID);
242 
248  void resetCommunication(uint8 iNodeID);
249 
251 
252 public:
255 
261  CANOpenNodeStatusFuture getNodeStatus(uint8 iNodeID);
262 
264 
265 protected:
268 
269  void onDestructFuture(uint64 requestID);
270 
272 
273 private:
275  void processNMTMessage(const CANMessage& iMsg);
276 
278  void processThread();
279 
280 private:
281 
283  // Internal class for handling node status requests
284 
285  class StatusRequest
286  {
287  public:
288  StatusRequest(uint8 iNode) : node(iNode) {}
289  virtual ~StatusRequest() {}
290  public:
291  virtual void setStatus(CANOpenNodeStatus iStatus) {
292  promise.set_value(iStatus);
293  }
294  virtual void setException(const Exception& ex) {
295  promise.set_exception(boost::copy_exception(ex));
296  }
297  public:
298  uint8 node;
299  boost::promise<CANOpenNodeStatus> promise;
300  };
301 
302  typedef boost::shared_ptr<StatusRequest> StatusRequestPtr;
303  typedef std::map<uint64, StatusRequestPtr> StatusRequestList;
304 
305  struct HeartbeatListener {
306  uint32 id;
307  CANOpenHeartbeat func;
308  };
309 
310 private:
311  // The CAN interface
312  CANInterfacePtr mCAN;
313  uint32 mCallbackID1;
314  uint32 mCallbackID2;
315 
316  // queue of incoming messages
317  std::queue<CANMessage> mMessageQueue;
318  boost::mutex mMessageMutex;
319  boost::condition_variable mMessageCondition;
320 
321  // internal processing thread
322  boost::thread mProcessThread;
323 
324  // list of heartbeat callbacks
325  std::vector<HeartbeatListener> mHeartbeatCbs;
326  uint32 mHeartbeatCallbackNextID;
327  boost::mutex mHeartbeatMutex;
328 
329  // list of pending status requests
330  StatusRequestList mStatusRequests;
331  boost::mutex mStatusRequestsMutex;
332 };
333 
335 typedef boost::shared_ptr<CANOpenNMTMaster> CANOpenNMTMasterPtr;
336 
338 
339 }} // namespaces
340 
341 #endif
bool timedWait(Duration const &relTime) const
Waits and blocks the current thread until the result of the associated status request is ready...
Definition: CANOpenNMTMaster.h:132
boost::function< void(uint8, CANOpenNodeStatus)> CANOpenHeartbeat
A callback for CANopen heartbeat message.
Definition: CANOpenNMTMaster.h:60
Abstract class for a hardware specific CAN driver.
bool isReady() const
Checks to see if the result of the status request associated with this future is set.
Definition: CANOpenNMTMaster.h:104
An implementation of a basic CANopen NMT master.
Definition: CANOpenNMTMaster.h:173
boost::shared_ptr< CANInterface > CANInterfacePtr
A shared pointer of the CANInterface.
Definition: CANInterface.h:224
CANOpenNodeStatusFuture()
Default constructor.
Definition: CANOpenNMTMaster.h:76
CANOpenNodeStatusFuture(CANOpenNodeStatusFuture &&other)
Move constructor.
Definition: CANOpenNMTMaster.h:87
Wrapper for boost::unique_future that is specialized for NMT status requests.
Definition: CANOpenNMTMaster.h:71
Global definitions of the CANopen standard.
bool timedWaitUntil(boost::system_time const &absTime) const
Waits and blocks the current thread until the result of the associated status request is ready...
Definition: CANOpenNMTMaster.h:142
CANOpenNMTMaster * mNMTMaster
Definition: CANOpenNMTMaster.h:163
boost::shared_ptr< CANOpenNMTMaster > CANOpenNMTMasterPtr
A shared pointer of the CANOpenNMTMaster.
Definition: CANOpenNMTMaster.h:335
CANOpenNodeStatusFuture & operator=(CANOpenNodeStatusFuture &&other)
Move assignment operator.
Definition: CANOpenNMTMaster.h:92
uint64 mRequestID
Definition: CANOpenNMTMaster.h:164
CANOpenNodeStatus
The different CANopen node states.
Definition: CANOpenDefs.h:154
bool hasException() const
Returns true if the status request associated with this future has finished with an exception rather ...
Definition: CANOpenNMTMaster.h:110
#define MLAB_CAN_EXPORT
Definition: CANExports.h:57
void wait() const
Waits and blocks the current thread until the result of the associated status request is ready...
Definition: CANOpenNMTMaster.h:123
A definition of a CAN message.
Definition: CANDefs.h:105
boost::unique_future< CANOpenNodeStatus > mFuture
Definition: CANOpenNMTMaster.h:165
bool hasValue() const
Returns true if the status request call associated with this future has finished with a return value ...
Definition: CANOpenNMTMaster.h:116
void swap(CANOpenNodeStatusFuture &other)
Swaps ownership of the asynchronous results associated with other and *this.
Definition: CANOpenNMTMaster.h:147
CANOpenNodeStatusFuture(boost::unique_future< CANOpenNodeStatus > other, CANOpenNMTMaster *master, uint64 requestID)
Constructor.
Definition: CANOpenNMTMaster.h:79