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>
29
30#include <chrono>
31#include <memory>
32#include <tuple>
33
34namespace lely {
35
36// The CAN network interface from <lely/can/net.hpp>.
37class CANNet;
38
39// The CANopen device from <lely/co/dev.hpp>.
40class CODev;
41
42// The CANopen Client-SDO service from <lely/co/csdo.hpp>.
43class COCSDO;
44
45namespace canopen {
46
48class 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
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
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_
An opaque CAN network interface type.
Definition: net.hpp:83
An opaque CANopen Client-SDO service type.
Definition: csdo.hpp:156
An opaque CANopen device type.
Definition: dev.hpp:76
An SDO download request.
Definition: sdo.hpp:132
DownloadRequest(aio::ExecutorBase &exec, F &&con)
Constructs an empty SDO download request.
Definition: sdo.hpp:146
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
An SDO upload request.
Definition: sdo.hpp:197
UploadRequest(aio::ExecutorBase &exec, F &&con)
Constructs an empty SDO upload request.
Definition: sdo.hpp:211
UploadRequest(uint16_t idx, uint8_t subidx, aio::ExecutorBase &exec, F &&con, const duration &timeout)
Constructs an SDO upload request.
Definition: sdo.hpp:230
The Client-SDO queue.
Definition: sdo.hpp:48
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
::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 >::type SubmitUpload(UploadRequest< T > &req)
Queues an SDO upload request.
Definition: sdo.hpp:341
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
Sdo()
Default-constructs an invalid Client-SDO queue.
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,::std::size_t >::type CancelDownload(DownloadRequest< T > &req, SdoErrc ac)
Aborts an SDO download request.
Definition: sdo.hpp:334
::std::size_t Cancel(SdoErrc ac)
Aborts the ongoing and all pending SDO requests.
Definition: sdo.cpp:346
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
typename::std::enable_if< detail::IsCanopenType< T >::value >::type SubmitDownload(DownloadRequest< T > &req)
Queues an SDO download request.
Definition: sdo.hpp:295
~Sdo()
Destructs the Client-SDO queue.
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
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
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
SdoErrc
The SDO abort codes.
Definition: sdo_error.hpp:37
Global namespace for the Lely Industries N.V. libraries.
Definition: buf.hpp:32
STL namespace.
This header file is part of the C++ CANopen application library; it contains the SDO error declaratio...
The internal implementation of the Client-SDO queue.
Definition: sdo.cpp:55
If T is one of the CANopen basic or array types, provides the member constant value equal to true.
Definition: type_traits.hpp:59
This header file is part of the C++ CANopen application library; it contains the CANopen type traits.