22#ifndef LELY_COAPP_SDO_HPP_
23#define LELY_COAPP_SDO_HPP_
83template <class T, class V = typename ::std::decay<T>::type>
87 ::std::forward<T>(value));
100 ::std::error_code ec) {
114 ::std::error_code ec, const ::std::string& what_arg) {
129 ::std::error_code ec,
const char* what_arg) {
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();
166 SdoRequestBase(
ev_exec_t*
exec, uint16_t idx_ = 0, uint8_t subidx_ = 0,
168 const ::std::chrono::milliseconds& timeout_ = {})
171 (*
static_cast<SdoRequestBase*
>(task))();
178 SdoRequestBase(
const SdoRequestBase&) =
delete;
180 SdoRequestBase& operator=(
const SdoRequestBase&) =
delete;
182 virtual ~SdoRequestBase() =
default;
208 ::std::error_code
ec;
211 virtual void operator()() noexcept = 0;
213 virtual
void OnRequest(
void* data) noexcept = 0;
217class SdoDownloadRequestBase : public SdoRequestBase {
219 using SdoRequestBase::SdoRequestBase;
223 U&& value_,
bool block =
false,
224 const ::std::chrono::milliseconds&
timeout = {})
226 value(::std::forward<U>(value_)) {}
232class SdoDownloadDcfRequestBase :
public SdoRequestBase {
234 using SdoRequestBase::SdoRequestBase;
236 SdoDownloadDcfRequestBase(
ev_exec_t*
exec,
const uint8_t* begin_,
238 const ::std::chrono::milliseconds&
timeout = {})
242 const ::std::chrono::milliseconds&
timeout = {})
247 virtual ~SdoDownloadDcfRequestBase();
250 void Read(
const char* path);
262 const uint8_t*
end{
nullptr};
271 using SdoRequestBase::SdoRequestBase;
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_;
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_;
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_;
398class SdoDownloadRequestWrapper :
public SdoDownloadRequestBase<T> {
400 using Signature = void(uint8_t
id, uint16_t
idx, uint8_t
subidx,
401 ::std::error_code
ec);
403 template <
class U,
class F>
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_;
419class SdoDownloadDcfRequestWrapper :
public SdoDownloadDcfRequestBase {
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)) {}
432 SdoDownloadDcfRequestWrapper(
ev_exec_t*
exec,
const char* path, F&& con,
433 const ::std::chrono::milliseconds&
timeout)
435 con_(::std::forward<F>(con)) {}
438 SdoDownloadDcfRequestWrapper(
ev_exec_t*
exec, const ::std::string& path,
440 const ::std::chrono::milliseconds&
timeout)
441 : SdoDownloadDcfRequestBase(
exec, path.c_str(),
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);
590 friend class SdoDownloadRequest;
592 friend class SdoDownloadDcfRequest;
595 friend class SdoUploadRequest;
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 = {}) {
685 exec, idx, subidx, ::std::forward<T>(value), ::std::forward<F>(con),
691 typename ::std::enable_if<is_canopen<T>::value,
bool>::type
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 = {}) {
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 = {}) {
797 ::std::forward<F>(con), block, timeout));
802 typename ::std::enable_if<is_canopen<T>::value,
bool>::type
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 {
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,
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_;
SdoDownloadDcfRequest(ev_exec_t *exec, F &&con)
Constructs an empty SDO download DCF request.
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...
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.
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.
bool Abort(detail::SdoRequestBase &req)
Aborts a pending SDO request.
void Submit(detail::SdoRequestBase &req)
Queues an LSS 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...
bool Cancel(detail::SdoRequestBase &req, SdoErrc ac)
Cancels a pending SDO request.
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.
const uint8_t * end
A pointer to one past the last byte in the concise DCF.
void Read(const char *path)
Reads a concise DCF from the specified path.
const uint8_t * begin
A pointer the the first byte in a concise DCF (see object 1F22 in CiA 302-3 version 4....
T value
The value to be written.
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).
T value
The value received from the SDO server.
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...
Future< T, V > make_error_future(E &&error)
Creates a shared state of type #lely::util::Result<T, V> that is immediately ready,...
Future< void, E > make_empty_future()
Creates a shared state of type #lely::util::Result<void, E> that is immediately ready,...
Future< V, E > make_ready_future(T &&value)
Creates a shared state of type #lely::util::Result<V, E> that is immediately ready,...
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
The namespace for implementation details of the C++ CANopen application library.
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.
The namespace for the C++ CANopen application library.
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.
ev::Promise< T, ::std::exception_ptr > SdoPromise
A helper alias template for the type of promise used to store the result of an asynchronous SDO reque...
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 ...
ev::Future< T, ::std::exception_ptr > SdoFuture
A helper alias template for the type of future used to retrieve the result of an asynchronous SDO req...
detail::Success< void > success() noexcept
Returns an object that can be used to implicitly construct a successful lely::util::Result with a def...
detail::Failure< typename ::std::decay< E >::type > failure(E &&e) noexcept
Returns an object that can be used to implicitly construct a failure lely::util::Result with the spec...
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.