22#ifndef LELY_COAPP_SDO_HPP_
23#define LELY_COAPP_SDO_HPP_
74 return ev::make_empty_future<::std::exception_ptr>();
83template <class T, class V = typename ::std::decay<T>::type>
86 return ev::make_ready_future<::std::exception_ptr, V>(
87 ::std::forward<T>(value));
100 ::std::error_code ec) {
114 ::std::error_code ec, const ::std::string& what_arg) {
115 return ev::make_error_future<T>(
129 ::std::error_code ec,
const char* what_arg) {
130 return ev::make_error_future<T>(
139inline ::std::chrono::milliseconds
141 using ::std::chrono::milliseconds;
142 return timeout <= 0 ? milliseconds::max() : milliseconds(timeout);
146template <
class Rep,
class Period>
149 using ::std::chrono::duration;
150 using ::std::chrono::duration_cast;
151 using ::std::chrono::milliseconds;
153 if (d == duration<Rep, Period>::max())
return 0;
154 auto timeout = duration_cast<milliseconds>(d).count();
156 if (timeout < 1)
return 1;
157 if (timeout > ::std::numeric_limits<int>::max())
158 return ::std::numeric_limits<int>::max();
168 const ::std::chrono::milliseconds& timeout_ = {})
208 ::std::error_code
ec;
211 virtual void operator()() noexcept = 0;
213 virtual
void OnRequest(
void* data) noexcept = 0;
219 using SdoRequestBase::SdoRequestBase;
223 U&& value_,
bool block =
false,
224 const ::std::chrono::milliseconds&
timeout = {})
226 value(::std::forward<U>(value_)) {}
234 using SdoRequestBase::SdoRequestBase;
238 const ::std::chrono::milliseconds&
timeout = {})
242 const ::std::chrono::milliseconds&
timeout = {})
250 void Read(
const char* path);
256 const uint8_t* begin{
nullptr};
262 const uint8_t* end{
nullptr};
271 using SdoRequestBase::SdoRequestBase;
294 using Signature = void(uint8_t
id, uint16_t idx, uint8_t subidx,
295 ::std::error_code ec);
304 : detail::SdoDownloadRequestBase<T>(exec), con_(::
std::forward<F>(con)) {}
307 void operator()() noexcept final;
309 void OnRequest(
void* data) noexcept final;
311 ::
std::function<Signature> con_;
337 using Signature = void(uint8_t
id, uint16_t idx, uint8_t subidx,
338 ::std::error_code ec);
349 : detail::SdoDownloadDcfRequestBase(exec), con_(::
std::forward<F>(con)) {}
352 void operator()() noexcept final;
354 void OnRequest(
void* data) noexcept final;
356 ::
std::function<Signature> con_;
375 using Signature = void(uint8_t
id, uint16_t idx, uint8_t subidx,
376 ::std::error_code ec, T value);
385 : detail::SdoUploadRequestBase<T>(exec), con_(::
std::forward<F>(con)) {}
388 void operator()() noexcept final;
390 void OnRequest(
void* data) noexcept final;
392 ::
std::function<Signature> con_;
400 using Signature = void(uint8_t
id, uint16_t idx, uint8_t subidx,
401 ::std::error_code ec);
403 template <
class U,
class F>
405 U&& value, F&& con,
bool block,
406 const ::std::chrono::milliseconds& timeout)
409 con_(::std::forward<F>(con)) {}
412 void operator()()
noexcept final;
414 void OnRequest(
void* data)
noexcept final;
416 ::std::function<Signature> con_;
421 using Signature = void(uint8_t
id, uint16_t idx, uint8_t subidx,
422 ::std::error_code ec);
426 const uint8_t* end, F&& con,
427 const ::std::chrono::milliseconds& timeout)
429 con_(::std::forward<F>(con)) {}
433 const ::std::chrono::milliseconds& timeout)
435 con_(::std::forward<F>(con)) {}
440 const ::std::chrono::milliseconds& timeout)
442 con_(::std::forward<F>(con)) {}
445 void operator()()
noexcept final;
447 void OnRequest(
void* data)
noexcept final;
449 ::std::function<Signature> con_;
455 using Signature = void(uint8_t
id, uint16_t idx, uint8_t subidx,
456 ::std::error_code ec, T value);
461 const ::std::chrono::milliseconds& timeout)
463 con_(::std::forward<F>(con)) {}
466 void operator()()
noexcept final;
468 void OnRequest(
void* data)
noexcept final;
470 ::std::function<Signature> con_;
495template <
class T,
class U,
class F>
498 U&& value, F&& con,
bool block =
false,
499 const ::std::chrono::milliseconds& timeout = {}) {
500 return new detail::SdoDownloadRequestWrapper<T>(
501 exec, idx, subidx, ::std::forward<U>(value), ::std::forward<F>(con),
526inline detail::SdoDownloadDcfRequestWrapper*
528 const uint8_t* end, F&& con,
529 const ::std::chrono::milliseconds& timeout = {}) {
530 return new detail::SdoDownloadDcfRequestWrapper(
531 exec, begin, end, ::std::forward<F>(con), timeout);
552inline detail::SdoDownloadDcfRequestWrapper*
554 const ::std::chrono::milliseconds& timeout = {}) {
555 return new detail::SdoDownloadDcfRequestWrapper(
556 exec, path, ::std::forward<F>(con), timeout);
578template <
class T,
class F>
579inline detail::SdoUploadRequestWrapper<T>*
582 const ::std::chrono::milliseconds& timeout = {}) {
583 return new detail::SdoUploadRequestWrapper<T>(
584 exec, idx, subidx, ::std::forward<F>(con), block, timeout);
643 Sdo& operator=(
const Sdo&) =
delete;
653 explicit operator bool() const noexcept {
return !!impl_; }
657 typename ::std::enable_if<is_canopen<T>::value>::type
679 template <class T, class F, class U = typename ::std::decay<T>::type>
680 typename ::std::enable_if<is_canopen<U>::value>::type
682 F&& con,
bool block =
false,
683 const ::std::chrono::milliseconds& timeout = {}) {
684 Submit(*make_sdo_download_request<U>(
685 exec, idx, subidx, ::std::forward<T>(value), ::std::forward<F>(con),
691 typename ::std::enable_if<is_canopen<T>::value,
bool>::type
693 return Cancel(req, ac);
698 typename ::std::enable_if<is_canopen<T>::value,
bool>::type
729 F&& con, const ::std::chrono::milliseconds& timeout = {}) {
731 ::std::forward<F>(con), timeout));
751 const ::std::chrono::milliseconds& timeout = {}) {
759 return Cancel(req, ac);
770 typename ::std::enable_if<is_canopen<T>::value>::type
791 template <
class T,
class F>
792 typename ::std::enable_if<is_canopen<T>::value>::type
795 const ::std::chrono::milliseconds& timeout = {}) {
796 Submit(*make_sdo_upload_request<T>(exec, idx, subidx,
797 ::std::forward<F>(con), block, timeout));
802 typename ::std::enable_if<is_canopen<T>::value,
bool>::type
804 return Cancel(req, ac);
809 typename ::std::enable_if<is_canopen<T>::value,
bool>::type
831 template <class T, class U = typename ::std::decay<T>::type>
835 const ::std::chrono::milliseconds& timeout = {}) {
838 exec, idx, subidx, ::std::forward<T>(value),
839 [p](uint8_t
id, uint16_t idx, uint8_t subidx,
840 ::std::error_code ec)
mutable {
845 p.
set(util::success());
868 SdoFuture<void> AsyncDownloadDcf(
869 ev_exec_t* exec,
const uint8_t* begin,
const uint8_t* end,
870 const ::std::chrono::milliseconds& timeout = {});
886 SdoFuture<void> AsyncDownloadDcf(
888 const ::std::chrono::milliseconds& timeout = {});
908 typename ::std::enable_if<is_canopen<T>::value, SdoFuture<T>>::type
910 const ::std::chrono::milliseconds& timeout = {}) {
914 [p](uint8_t
id, uint16_t idx, uint8_t subidx, ::std::error_code ec,
920 p.
set(util::success(::std::move(value)));
927 void Submit(detail::SdoRequestBase& req);
938 bool Cancel(detail::SdoRequestBase& req,
SdoErrc ac);
947 ::std::size_t CancelAll(
SdoErrc ac);
956 bool Abort(detail::SdoRequestBase& req);
964 ::std::size_t AbortAll();
968 ::std::unique_ptr<Impl_> impl_;
A series of SDO download (i.e., write) requests corresponding to the entries in a concise DCF.
void(uint8_t id, uint16_t idx, uint8_t subidx, ::std::error_code ec) Signature
The signature of the callback function invoked when all SDO download requests are successfully comple...
SdoDownloadDcfRequest(ev_exec_t *exec, F &&con)
Constructs an empty SDO download DCF request.
An SDO download (i.e., write) request.
void(uint8_t id, uint16_t idx, uint8_t subidx, ::std::error_code ec) Signature
The signature of the callback function invoked on completion of an SDO download request.
SdoDownloadRequest(ev_exec_t *exec, F &&con)
Constructs an empty SDO download request.
An SDO upload (i.e., read) request.
SdoUploadRequest(ev_exec_t *exec, F &&con)
Constructs an empty SDO upload request.
void(uint8_t id, uint16_t idx, uint8_t subidx, ::std::error_code ec, T value) Signature
The signature of the callback function invoked on completion of an SDO upload request.
typename::std::enable_if< is_canopen< T >::value, bool >::type AbortUpload(SdoUploadRequest< T > &req)
Aborts an SDO upload request.
typename::std::enable_if< is_canopen< T >::value >::type SubmitDownload(SdoDownloadRequest< T > &req)
Queues an SDO download request.
typename::std::enable_if< is_canopen< T >::value >::type SubmitUpload(ev_exec_t *exec, uint16_t idx, uint8_t subidx, F &&con, bool block=false, const ::std::chrono::milliseconds &timeout={})
Queues an SDO upload request.
Sdo()
Default-constructs an invalid Client-SDO queue.
typename::std::enable_if< is_canopen< T >::value, bool >::type CancelDownload(SdoDownloadRequest< T > &req, SdoErrc ac)
Cancels an SDO download request.
typename::std::enable_if< is_canopen< T >::value, bool >::type CancelUpload(SdoUploadRequest< T > &req, SdoErrc ac)
Cancels an SDO upload request.
bool AbortDownloadDcf(SdoDownloadDcfRequest &req)
Aborts an SDO download DCF request.
typename::std::enable_if< is_canopen< U >::value, SdoFuture< void > >::type AsyncDownload(ev_exec_t *exec, uint16_t idx, uint8_t subidx, T &&value, bool block=false, const ::std::chrono::milliseconds &timeout={})
Queues an asynchronous SDO download request and creates a future which becomes ready once the request...
typename::std::enable_if< is_canopen< T >::value, SdoFuture< T > >::type AsyncUpload(ev_exec_t *exec, uint16_t idx, uint8_t subidx, bool block=false, const ::std::chrono::milliseconds &timeout={})
Queues an asynchronous SDO upload request and creates a future which becomes ready once the request c...
void SubmitDownloadDcf(ev_exec_t *exec, const uint8_t *begin, const uint8_t *end, F &&con, const ::std::chrono::milliseconds &timeout={})
Queues an SDO download DCF request.
typename::std::enable_if< is_canopen< T >::value >::type SubmitUpload(SdoUploadRequest< T > &req)
Queues an SDO upload request.
void SubmitDownloadDcf(SdoDownloadDcfRequest &req)
Queues an SDO download DCF request.
~Sdo()
Destructs the Client-SDO queue.
void SubmitDownloadDcf(ev_exec_t *exec, const char *path, F &&con, const ::std::chrono::milliseconds &timeout={})
Queues an SDO download DCF request.
typename::std::enable_if< is_canopen< T >::value, bool >::type AbortDownload(SdoDownloadRequest< T > &req)
Aborts an SDO download request.
typename::std::enable_if< is_canopen< U >::value >::type SubmitDownload(ev_exec_t *exec, uint16_t idx, uint8_t subidx, T &&value, F &&con, bool block=false, const ::std::chrono::milliseconds &timeout={})
Queues an SDO download request.
bool CancelDownloadDcf(SdoDownloadDcfRequest &req, SdoErrc ac)
Cancels an SDO download request.
uint16_t idx
The object index.
::std::chrono::milliseconds timeout
The SDO timeout.
ev::Executor GetExecutor() const noexcept
Returns the executor to which the completion task is (to be) submitted.
bool block
A flag specifying whether the request should use a block SDO instead of a segmented (or expedited) SD...
uint8_t subidx
The object sub-index.
::std::error_code ec
The SDO abort code (0 on success).
An abstract task executor. This class is a wrapper around #ev_exec_t*.
Future< T, E > get_future() const noexcept
Returns a lely::ev::Future with (a reference to) the same shared state as *this.
bool set(U &&u)
Satisfies a promise, if it was not aready satisfied, and stores the specified value as the result in ...
This header file is part of the C++ CANopen application library; it contains the CANopen type traits.
This header file is part of the event library; it contains the C++ interface for the futures and prom...
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
inline ::std::chrono::milliseconds from_sdo_timeout(int timeout)
Converts an SDO timeout to a duration.
int to_sdo_timeout(const ::std::chrono::duration< Rep, Period > &d)
Converts a duration to an SDO timeout.
SdoFuture< void > make_empty_sdo_future()
Returns an SDO future with a shared state that is immediately ready, containing a successful result o...
detail::SdoUploadRequestWrapper< T > * make_sdo_upload_request(ev_exec_t *exec, uint16_t idx, uint8_t subidx, F &&con, bool block=false, const ::std::chrono::milliseconds &timeout={})
Creates an SDO upload request with a completion task.
detail::SdoDownloadRequestWrapper< T > * make_sdo_download_request(ev_exec_t *exec, uint16_t idx, uint8_t subidx, U &&value, F &&con, bool block=false, const ::std::chrono::milliseconds &timeout={})
Creates an SDO download request with a completion task.
SdoErrc
The SDO abort codes.
detail::SdoDownloadDcfRequestWrapper * make_sdo_download_dcf_request(ev_exec_t *exec, const uint8_t *begin, const uint8_t *end, F &&con, const ::std::chrono::milliseconds &timeout={})
Creates a series of SDO download requests, corresponding to the entries in a concise DCF,...
SdoFuture< V > make_ready_sdo_future(T &&value)
Returns an SDO future with a shared state that is immediately ready, containing a successful result c...
SdoFuture< T > make_error_sdo_future(uint8_t id, uint16_t idx, uint8_t subidx, ::std::error_code ec)
Returns an SDO future with a shared state that is immediately ready, containing a failure result cons...
::std::exception_ptr make_sdo_exception_ptr(uint8_t id, uint16_t idx, uint8_t subidx, ::std::error_code ec) noexcept
Creates an std::exception_ptr that holds a reference to a lely::canopen::SdoError with the specified ...
This header file is part of the C++ CANopen application library; it contains the SDO error declaratio...
ev_exec_t * exec
A pointer to the executor to which the task is (to be) submitted.
#define EV_TASK_INIT(exec, func)
The static initializer for ev_task.