Lely core libraries  1.9.2
sdo.hpp
Go to the documentation of this file.
1 
22 #ifndef LELY_COAPP_SDO_HPP_
23 #define LELY_COAPP_SDO_HPP_
24 
25 #include <lely/aio/exec.hpp>
26 #include <lely/aio/future.hpp>
28 #include <lely/coapp/sdo_error.hpp>
29 
30 #include <chrono>
31 #include <memory>
32 #include <tuple>
33 
34 namespace lely {
35 
36 // The CAN network interface from <lely/can/net.hpp>.
37 class CANNet;
38 
39 // The CANopen device from <lely/co/dev.hpp>.
40 class CODev;
41 
42 // The CANopen Client-SDO service from <lely/co/csdo.hpp>.
43 class COCSDO;
44 
45 namespace canopen {
46 
48 class Sdo {
49  public:
51  using duration = ::std::chrono::milliseconds;
52 
53  private:
54  struct Impl_;
55 
56  class RequestBase_ : public aio_task {
57  friend class Sdo;
58 
59  public:
60  RequestBase_(aio::ExecutorBase& exec, aio_task_func_t* func)
61  : aio_task AIO_TASK_INIT(exec, func) {}
62 
63  RequestBase_(aio::ExecutorBase& exec, aio_task_func_t* func, uint16_t idx_,
64  uint8_t subidx_, const duration& timeout_)
65  : aio_task AIO_TASK_INIT(exec, func),
66  idx(idx_),
67  subidx(subidx_),
68  timeout(timeout_) {}
69 
70  RequestBase_(const RequestBase_&) = delete;
71 
72  RequestBase_& operator=(const RequestBase_&) = delete;
73 
74  virtual ~RequestBase_() = default;
75 
76  aio::ExecutorBase
77  GetExecutor() const noexcept {
78  return aio::ExecutorBase(exec);
79  }
80 
81  uint16_t idx{0};
82  uint8_t subidx{0};
83  duration timeout{};
84  uint32_t ac{0};
85 
86  private:
87  virtual void OnRequest(Impl_* impl) noexcept = 0;
88  };
89 
90  template <class T>
91  class DownloadRequestBase_ : public RequestBase_ {
92  public:
93  DownloadRequestBase_(aio::ExecutorBase& exec, aio_task_func_t* func)
94  : RequestBase_(exec, func) {}
95 
96  template <class U>
97  DownloadRequestBase_(aio::ExecutorBase& exec, aio_task_func_t* func,
98  uint16_t idx, uint8_t subidx, U&& value_,
99  const duration& timeout)
100  : RequestBase_(exec, func, idx, subidx, timeout),
101  value(::std::forward<U>(value_)) {}
102 
103  T value{};
104  };
105 
106  template <class T>
107  class UploadRequestBase_ : public RequestBase_ {
108  friend Impl_;
109 
110  public:
111  using RequestBase_::RequestBase_;
112 
113  T value{};
114  };
115 
116  public:
127  using DownloadSignature = void(uint16_t idx, uint8_t subidx,
128  ::std::error_code ec);
129 
131  template <class T>
132  class DownloadRequest : public DownloadRequestBase_<T> {
133  public:
145  template <class F>
146  DownloadRequest(aio::ExecutorBase& exec, F&& con)
147  : DownloadRequestBase_<T>(exec, &Func_), con_(::std::forward<F>(con)) {}
148 
165  template <class U, class F>
166  DownloadRequest(uint16_t idx, uint8_t subidx, U&& value,
167  aio::ExecutorBase& exec, F&& con, const duration& timeout)
168  : DownloadRequestBase_<T>(exec, &Func_, idx, subidx,
169  ::std::forward<U>(value), timeout),
170  con_(::std::forward<F>(con)) {}
171 
172  private:
173  void OnRequest(Impl_* impl) noexcept override;
174 
175  static void Func_(aio_task* task) noexcept;
176 
177  ::std::function<DownloadSignature> con_{nullptr};
178  };
179 
191  template <class T>
192  using UploadSignature = void(uint16_t idx, uint8_t subidx,
193  ::std::error_code ec, T value);
194 
196  template <class T>
197  class UploadRequest : public UploadRequestBase_<T> {
198  public:
210  template <class F>
211  UploadRequest(aio::ExecutorBase& exec, F&& con)
212  : UploadRequestBase_<T>(exec, &Func_), con_(::std::forward<F>(con)) {}
213 
229  template <class F>
230  UploadRequest(uint16_t idx, uint8_t subidx, aio::ExecutorBase& exec,
231  F&& con, const duration& timeout)
232  : UploadRequestBase_<T>(exec, &Func_, idx, subidx, timeout),
233  con_(::std::forward<F>(con)) {}
234 
235  private:
236  void OnRequest(Impl_* impl) noexcept override;
237 
238  static void Func_(aio_task* task) noexcept;
239 
240  ::std::function<UploadSignature<T>> con_{nullptr};
241  };
242 
244  Sdo();
245 
254  Sdo(CANNet* net, uint8_t id);
255 
265  Sdo(CANNet* net, CODev* dev, uint8_t num);
266 
275  explicit Sdo(COCSDO* sdo);
276 
277  Sdo(const Sdo&) = delete;
278  Sdo(Sdo&&) = default;
279 
280  Sdo& operator=(const Sdo&) = delete;
281  Sdo& operator=(Sdo&&);
282 
287  ~Sdo();
288 
290  explicit operator bool() const noexcept { return !!impl_; }
291 
293  template <class T>
294  typename ::std::enable_if<detail::IsCanopenType<T>::value>::type
296  Submit(static_cast<RequestBase_&>(req));
297  }
298 
314  template <class T, class F, class U = typename ::std::decay<T>::type>
315  typename ::std::enable_if<
317  SubmitDownload(uint16_t idx, uint8_t subidx, T&& value,
318  aio::ExecutorBase& exec, F&& con, const duration& timeout) {
319  auto req =
320  new DownloadRequestWrapper<U>(idx, subidx, ::std::forward<T>(value),
321  exec, ::std::forward<F>(con), timeout);
322  Submit(*req);
323  }
324 
331  template <class T>
332  typename ::std::enable_if<detail::IsCanopenType<T>::value,
333  ::std::size_t>::type
335  return Cancel(req, ac);
336  }
337 
339  template <class T>
340  typename ::std::enable_if<detail::IsCanopenType<T>::value>::type
342  Submit(static_cast<RequestBase_&>(req));
343  }
344 
359  template <class T, class F>
360  typename ::std::enable_if<detail::IsCanopenType<T>::value>::type
361  SubmitUpload(uint16_t idx, uint8_t subidx, aio::ExecutorBase& exec, F&& con,
362  const duration& timeout) {
363  auto req = new UploadRequestWrapper<T>(idx, subidx, exec,
364  ::std::forward<F>(con), timeout);
365  Submit(*req);
366  }
367 
374  template <class T>
375  typename ::std::enable_if<detail::IsCanopenType<T>::value,
376  ::std::size_t>::type
378  return Cancel(req, ac);
379  }
380 
386  ::std::size_t Cancel(SdoErrc ac);
387 
404  template <class T, class U = typename ::std::decay<T>::type>
405  typename ::std::enable_if<detail::IsCanopenType<U>::value,
406  aio::Future<::std::error_code>>::type
407  AsyncDownload(aio::LoopBase& loop, aio::ExecutorBase& exec, int16_t idx,
408  uint8_t subidx, T&& value, const duration& timeout) {
409  auto req = new AsyncDownloadRequest<U>(loop, exec, idx, subidx,
410  ::std::forward<T>(value), timeout);
411  Submit(*req);
412  return req->GetFuture();
413  }
414 
431  template <class T>
432  typename ::std::enable_if<
434  aio::Future<::std::tuple<::std::error_code, T>>>::type
435  AsyncUpload(aio::LoopBase& loop, aio::ExecutorBase& exec, int16_t idx,
436  uint8_t subidx, const duration& timeout) {
437  auto req = new AsyncUploadRequest<T>(loop, exec, idx, subidx, timeout);
438  Submit(*req);
439  return req->GetFuture();
440  }
441 
442  private:
443  template <class T>
444  class DownloadRequestWrapper : public DownloadRequestBase_<T> {
445  public:
446  template <class U, class F>
447  DownloadRequestWrapper(uint16_t idx, int8_t subidx, U&& value,
448  aio::ExecutorBase& exec, F&& con,
449  const duration& timeout)
450  : DownloadRequestBase_<T>(exec, &Func_, idx, subidx,
451  ::std::forward<U>(value), timeout),
452  con_(::std::forward<F>(con)) {}
453 
454  private:
455  ~DownloadRequestWrapper() = default;
456 
457  void OnRequest(Impl_* impl) noexcept override;
458 
459  static void Func_(aio_task* task) noexcept;
460 
461  ::std::function<DownloadSignature> con_{nullptr};
462  };
463 
464  template <class T>
465  class UploadRequestWrapper : public UploadRequestBase_<T> {
466  public:
467  template <class F>
468  UploadRequestWrapper(uint16_t idx, uint8_t subidx, aio::ExecutorBase& exec,
469  F&& con, const duration& timeout)
470  : UploadRequestBase_<T>(exec, &Func_, idx, subidx, timeout),
471  con_(::std::forward<F>(con)) {}
472 
473  private:
474  ~UploadRequestWrapper() = default;
475 
476  void OnRequest(Impl_* impl) noexcept override;
477 
478  static void Func_(aio_task* task) noexcept;
479 
480  ::std::function<UploadSignature<T>> con_{nullptr};
481  };
482 
483  template <class T>
484  class AsyncDownloadRequest : public DownloadRequestBase_<T> {
485  public:
486  template <class U>
487  AsyncDownloadRequest(aio::LoopBase& loop, aio::ExecutorBase& exec,
488  uint16_t idx, int8_t subidx, U&& value,
489  const duration& timeout)
490  : DownloadRequestBase_<T>(exec, &Func_, idx, subidx,
491  ::std::forward<U>(value), timeout),
492  promise_(loop, exec) {}
493 
494  aio::Future<::std::error_code>
495  GetFuture() noexcept {
496  return promise_.GetFuture();
497  }
498 
499  private:
500  ~AsyncDownloadRequest() = default;
501 
502  void OnRequest(Impl_* impl) noexcept override;
503 
504  static void Func_(aio_task* task) noexcept;
505 
506  aio::Promise<::std::error_code> promise_;
507  };
508 
509  template <class T>
510  class AsyncUploadRequest : public UploadRequestBase_<T> {
511  public:
512  AsyncUploadRequest(aio::LoopBase& loop, aio::ExecutorBase& exec,
513  uint16_t idx, int8_t subidx, const duration& timeout)
514  : UploadRequestBase_<T>(exec, &Func_, idx, subidx, timeout),
515  promise_(loop, exec) {}
516 
517  aio::Future<::std::tuple<::std::error_code, T>>
518  GetFuture() noexcept {
519  return promise_.GetFuture();
520  }
521 
522  private:
523  ~AsyncUploadRequest() = default;
524 
525  void OnRequest(Impl_* impl) noexcept override;
526 
527  static void Func_(aio_task* task) noexcept;
528 
529  aio::Promise<::std::tuple<::std::error_code, T>> promise_;
530  };
531 
532  void Submit(RequestBase_& req);
533 
534  ::std::size_t Cancel(RequestBase_& req, SdoErrc ac);
535 
536  ::std::unique_ptr<Impl_> impl_;
537 };
538 
539 } // namespace canopen
540 
541 } // namespace lely
542 
543 #endif // LELY_COAPP_SDO_HPP_
The internal implementation of the Client-SDO queue.
Definition: sdo.cpp:55
typename ::std::enable_if< detail::IsCanopenType< T >::value, ::std::size_t >::type CancelDownload(DownloadRequest< T > &req, SdoErrc ac)
Aborts an SDO download request.
Definition: sdo.hpp:334
This header file is part of the C++ CANopen application library; it contains the SDO error declaratio...
UploadRequest(aio::ExecutorBase &exec, F &&con)
Constructs an empty SDO upload request.
Definition: sdo.hpp:211
typename ::std::enable_if< detail::IsCanopenType< typename ::std::decay< U >::type >::value >::type SubmitDownload(uint16_t idx, uint8_t subidx, T &&value, aio::ExecutorBase &exec, F &&con, const duration &timeout)
Queues an SDO download request.
Definition: sdo.hpp:317
Sdo()
Default-constructs an invalid Client-SDO queue.
STL namespace.
An opaque CANopen Client-SDO service type.
Definition: csdo.hpp:156
An SDO download request.
Definition: sdo.hpp:132
typename ::std::enable_if< detail::IsCanopenType< T >::value >::type SubmitDownload(DownloadRequest< T > &req)
Queues an SDO download request.
Definition: sdo.hpp:295
An opaque CANopen device type.
Definition: dev.hpp:76
typename ::std::enable_if< detail::IsCanopenType< T >::value >::type SubmitUpload(uint16_t idx, uint8_t subidx, aio::ExecutorBase &exec, F &&con, const duration &timeout)
Queues an SDO upload request.
Definition: sdo.hpp:361
An SDO upload request.
Definition: sdo.hpp:197
If T is one of the CANopen basic or array types, provides the member constant value equal to true...
Definition: type_traits.hpp:57
::std::chrono::milliseconds duration
The type used to represent an SDO timeout duration.
Definition: sdo.hpp:51
typename ::std::enable_if< detail::IsCanopenType< T >::value, ::std::size_t >::type CancelUpload(UploadRequest< T > &req, SdoErrc ac)
Aborts an SDO upload request.
Definition: sdo.hpp:377
SdoErrc
The SDO abort codes.
Definition: sdo_error.hpp:37
~Sdo()
Destructs the Client-SDO queue.
typename ::std::enable_if< detail::IsCanopenType< T >::value, aio::Future<::std::tuple<::std::error_code, T > > >::type AsyncUpload(aio::LoopBase &loop, aio::ExecutorBase &exec, int16_t idx, uint8_t subidx, const duration &timeout)
Queues an asynchronous SDO upload request and returns a future.
Definition: sdo.hpp:435
typename ::std::enable_if< detail::IsCanopenType< U >::value, aio::Future<::std::error_code > >::type AsyncDownload(aio::LoopBase &loop, aio::ExecutorBase &exec, int16_t idx, uint8_t subidx, T &&value, const duration &timeout)
Queues an asynchronous SDO download request and returns a future.
Definition: sdo.hpp:407
This header file is part of the C++ CANopen application library; it contains the CANopen type traits...
UploadRequest(uint16_t idx, uint8_t subidx, aio::ExecutorBase &exec, F &&con, const duration &timeout)
Constructs an SDO upload request.
Definition: sdo.hpp:230
void(uint16_t idx, uint8_t subidx, ::std::error_code ec, T value) UploadSignature
The signature of the callback function invoked on completion of an SDO upload request.
Definition: sdo.hpp:193
typename ::std::enable_if< detail::IsCanopenType< T >::value >::type SubmitUpload(UploadRequest< T > &req)
Queues an SDO upload request.
Definition: sdo.hpp:341
::std::size_t Cancel(SdoErrc ac)
Aborts the ongoing and all pending SDO requests.
Definition: sdo.cpp:346
The Client-SDO queue.
Definition: sdo.hpp:48
Global namespace for the Lely Industries N.V. libraries.
Definition: buf.hpp:32
An opaque CAN network interface type.
Definition: net.hpp:83
DownloadRequest(uint16_t idx, uint8_t subidx, U &&value, aio::ExecutorBase &exec, F &&con, const duration &timeout)
Constructs an SDO download request.
Definition: sdo.hpp:166
DownloadRequest(aio::ExecutorBase &exec, F &&con)
Constructs an empty SDO download request.
Definition: sdo.hpp:146
void(uint16_t idx, uint8_t subidx, ::std::error_code ec) DownloadSignature
The signature of the callback function invoked on completion of an SDO download request.
Definition: sdo.hpp:128