26#if !LELY_NO_COAPP_SLAVE
50 netid()
const noexcept {
63 static constexpr uint32_t Key(uint16_t idx, uint8_t subidx)
noexcept;
64 static uint32_t Key(
const co_sub_t* sub)
noexcept;
73 ::std::function<void(
bool)> on_life_guarding;
78 const ::std::string& dcf_bin, uint8_t
id)
79 :
Node(exec, timer, chan, dcf_txt, dcf_bin,
id),
82BasicSlave::~BasicSlave() =
default;
85typename ::std::enable_if<is_canopen<T>::value>::type
89 OnRead<T>(idx, subidx, ::std::move(ind), ec);
90 if (ec)
throw SdoError(impl_->id(), idx, subidx, ec);
95template <
class T,
class F>
99 using c_type =
typename traits::c_type;
108 auto value = traits::from_c_type(*pval);
111 ac =
static_cast<uint32_t
>(ec.value());
114 auto val = traits::to_c_type(value, ec);
115 ac =
static_cast<uint32_t
>(ec.value());
117 traits::destroy(val);
126typename ::std::enable_if<is_canopen<T>::value>::type
129 ::std::error_code& ec) {
148 auto key = Impl_::Key(sub);
151 return OnUpInd<T>(sub, req, ind);
156 void* data)
noexcept -> uint32_t {
157 auto self =
static_cast<Impl_*
>(data);
158 auto it = self->up_ind.find(self->Key(sub));
159 if (it == self->up_ind.end())
return 0;
160 return it->second(sub, req);
169typename ::std::enable_if<is_canopen<T>::value>::type
171 uint8_t n = (*this)[idx][0];
172 for (uint8_t i = 1; i <= n; i++) OnRead<T>(idx, i, ind);
176typename ::std::enable_if<is_canopen<T>::value>::type
178 ::std::error_code& ec) {
179 uint8_t n = (*this)[idx][0].Get<uint8_t>(ec);
180 for (uint8_t i = 1; i <= n && !ec; i++) OnRead<T>(idx, i, ind, ec);
184typename ::std::enable_if<is_canopen<T>::value>::type
187 ::std::error_code ec;
188 OnWrite<T>(idx, subidx, ::std::move(ind), ec);
189 if (ec)
throw SdoError(impl_->id(), idx, subidx, ec);
194template <
class T,
class F>
195typename ::std::enable_if<is_canopen_basic<T>::value, uint32_t>::type
198 using c_type =
typename traits::c_type;
211 ac =
static_cast<uint32_t
>(ec.value());
216 traits::destroy(val);
220template <
class T,
class F>
221typename ::std::enable_if<!is_canopen_basic<T>::value, uint32_t>::type
223 using traits = canopen_traits<T>;
224 using c_type =
typename traits::c_type;
234 auto value = traits::from_c_type(val);
238 traits::destroy(val);
239 val = traits::to_c_type(value, ec);
241 ac =
static_cast<uint32_t
>(ec.value());
246 traits::destroy(val);
253typename ::std::enable_if<is_canopen<T>::value>::type
256 ::std::error_code& ec) {
275 auto key = Impl_::Key(sub);
278 return OnDnInd<T>(sub, req, ind);
283 auto self =
static_cast<Impl_*
>(data);
284 auto it = self->dn_ind.find(self->Key(sub));
285 if (it == self->dn_ind.end())
return 0;
286 return it->second(sub, req);
295typename ::std::enable_if<is_canopen<T>::value>::type
297 uint8_t n = (*this)[idx][0];
298 for (uint8_t i = 1; i <= n; i++) OnWrite<T>(idx, i, ind);
302typename ::std::enable_if<is_canopen<T>::value>::type
304 ::std::error_code& ec) {
305 uint8_t n = (*this)[idx][0].Get<uint8_t>(ec);
306 for (uint8_t i = 1; i <= n && !ec; i++) OnWrite<T>(idx, i, ind, ec);
309#ifndef DOXYGEN_SHOULD_SKIP_THIS
313 ::std::function<OnReadSignature<bool>>);
315 ::std::function<OnReadSignature<bool>>,
318 ::std::function<OnReadSignature<bool>>);
320 ::std::function<OnReadSignature<bool>>,
323 uint16_t, uint8_t, ::std::function<OnWriteSignature<bool>>);
325 ::std::function<OnWriteSignature<bool>>,
328 uint16_t, ::std::function<OnWriteSignature<bool>>);
330 ::std::function<OnWriteSignature<bool>>,
335 uint16_t, uint8_t, ::std::function<OnReadSignature<int8_t>>);
337 uint16_t, uint8_t, ::std::function<OnReadSignature<int8_t>>,
340 uint16_t, ::std::function<OnReadSignature<int8_t>>);
342 uint16_t, ::std::function<OnReadSignature<int8_t>>, ::std::error_code&);
344 uint16_t, uint8_t, ::std::function<OnWriteSignature<int8_t>>);
346 uint16_t, uint8_t, ::std::function<OnWriteSignature<int8_t>>,
349 uint16_t, ::std::function<OnWriteSignature<int8_t>>);
351 uint16_t, ::std::function<OnWriteSignature<int8_t>>, ::std::error_code&);
355 uint16_t, uint8_t, ::std::function<OnReadSignature<int16_t>>);
357 uint16_t, uint8_t, ::std::function<OnReadSignature<int16_t>>,
360 uint16_t, ::std::function<OnReadSignature<int16_t>>);
362 uint16_t, ::std::function<OnReadSignature<int16_t>>, ::std::error_code&);
364 uint16_t, uint8_t, ::std::function<OnWriteSignature<int16_t>>);
366 uint16_t, uint8_t, ::std::function<OnWriteSignature<int16_t>>,
369 uint16_t, ::std::function<OnWriteSignature<int16_t>>);
371 uint16_t, ::std::function<OnWriteSignature<int16_t>>, ::std::error_code&);
375 uint16_t, uint8_t, ::std::function<OnReadSignature<int32_t>>);
377 uint16_t, uint8_t, ::std::function<OnReadSignature<int32_t>>,
380 uint16_t, ::std::function<OnReadSignature<int32_t>>);
382 uint16_t, ::std::function<OnReadSignature<int32_t>>, ::std::error_code&);
384 uint16_t, uint8_t, ::std::function<OnWriteSignature<int32_t>>);
386 uint16_t, uint8_t, ::std::function<OnWriteSignature<int32_t>>,
389 uint16_t, ::std::function<OnWriteSignature<int32_t>>);
391 uint16_t, ::std::function<OnWriteSignature<int32_t>>, ::std::error_code&);
395 uint16_t, uint8_t, ::std::function<OnReadSignature<uint8_t>>);
397 uint16_t, uint8_t, ::std::function<OnReadSignature<uint8_t>>,
400 uint16_t, ::std::function<OnReadSignature<uint8_t>>);
402 uint16_t, ::std::function<OnReadSignature<uint8_t>>, ::std::error_code&);
404 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint8_t>>);
406 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint8_t>>,
409 uint16_t, ::std::function<OnWriteSignature<uint8_t>>);
411 uint16_t, ::std::function<OnWriteSignature<uint8_t>>, ::std::error_code&);
415 uint16_t, uint8_t, ::std::function<OnReadSignature<uint16_t>>);
417 uint16_t, uint8_t, ::std::function<OnReadSignature<uint16_t>>,
420 uint16_t, ::std::function<OnReadSignature<uint16_t>>);
422 uint16_t, ::std::function<OnReadSignature<uint16_t>>, ::std::error_code&);
424 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint16_t>>);
426 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint16_t>>,
429 uint16_t, ::std::function<OnWriteSignature<uint16_t>>);
431 uint16_t, ::std::function<OnWriteSignature<uint16_t>>, ::std::error_code&);
435 uint16_t, uint8_t, ::std::function<OnReadSignature<uint32_t>>);
437 uint16_t, uint8_t, ::std::function<OnReadSignature<uint32_t>>,
440 uint16_t, ::std::function<OnReadSignature<uint32_t>>);
442 uint16_t, ::std::function<OnReadSignature<uint32_t>>, ::std::error_code&);
444 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint32_t>>);
446 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint32_t>>,
449 uint16_t, ::std::function<OnWriteSignature<uint32_t>>);
451 uint16_t, ::std::function<OnWriteSignature<uint32_t>>, ::std::error_code&);
455 uint16_t, uint8_t, ::std::function<OnReadSignature<float>>);
457 ::std::function<OnReadSignature<float>>,
460 uint16_t, ::std::function<OnReadSignature<float>>);
462 ::std::function<OnReadSignature<float>>,
465 uint16_t, uint8_t, ::std::function<OnWriteSignature<float>>);
467 uint16_t, uint8_t, ::std::function<OnWriteSignature<float>>,
470 uint16_t, ::std::function<OnWriteSignature<float>>);
472 uint16_t, ::std::function<OnWriteSignature<float>>, ::std::error_code&);
476 uint16_t, uint8_t, ::std::function<OnReadSignature<::std::string>>);
478 uint16_t, uint8_t, ::std::function<OnReadSignature<::std::string>>,
481 uint16_t, ::std::function<OnReadSignature<::std::string>>);
483 uint16_t, ::std::function<OnReadSignature<::std::string>>,
486 uint16_t, uint8_t, ::std::function<OnWriteSignature<::std::string>>);
488 uint16_t, uint8_t, ::std::function<OnWriteSignature<::std::string>>,
491 uint16_t, ::std::function<OnWriteSignature<::std::string>>);
493 uint16_t, ::std::function<OnWriteSignature<::std::string>>,
499 ::std::function<OnReadSignature<::std::vector<uint8_t>>>);
501 uint16_t, uint8_t, ::std::function<OnReadSignature<::std::vector<uint8_t>>>,
504 uint16_t, ::std::function<OnReadSignature<::std::vector<uint8_t>>>);
506 uint16_t, ::std::function<OnReadSignature<::std::vector<uint8_t>>>,
510 ::std::function<OnWriteSignature<::std::vector<uint8_t>>>);
513 ::std::function<OnWriteSignature<::std::vector<uint8_t>>>,
516 uint16_t, ::std::function<OnWriteSignature<::std::vector<uint8_t>>>);
518 uint16_t, ::std::function<OnWriteSignature<::std::vector<uint8_t>>>,
524 ::std::function<OnReadSignature<::std::basic_string<char16_t>>>);
527 ::std::function<OnReadSignature<::std::basic_string<char16_t>>>,
530 uint16_t, ::std::function<OnReadSignature<::std::basic_string<char16_t>>>);
532 uint16_t, ::std::function<OnReadSignature<::std::basic_string<char16_t>>>,
536 ::std::function<OnWriteSignature<::std::basic_string<char16_t>>>);
539 ::std::function<OnWriteSignature<::std::basic_string<char16_t>>>,
542 uint16_t, ::std::function<OnWriteSignature<::std::basic_string<char16_t>>>);
544 uint16_t, ::std::function<OnWriteSignature<::std::basic_string<char16_t>>>,
554 uint16_t, uint8_t, ::std::function<OnReadSignature<double>>);
556 uint16_t, uint8_t, ::std::function<OnReadSignature<double>>,
559 uint16_t, ::std::function<OnReadSignature<double>>);
561 uint16_t, ::std::function<OnReadSignature<double>>, ::std::error_code&);
563 uint16_t, uint8_t, ::std::function<OnWriteSignature<double>>);
565 uint16_t, uint8_t, ::std::function<OnWriteSignature<double>>,
568 uint16_t, ::std::function<OnWriteSignature<double>>);
570 uint16_t, ::std::function<OnWriteSignature<double>>, ::std::error_code&);
578 uint16_t, uint8_t, ::std::function<OnReadSignature<int64_t>>);
580 uint16_t, uint8_t, ::std::function<OnReadSignature<int64_t>>,
583 uint16_t, ::std::function<OnReadSignature<int64_t>>);
585 uint16_t, ::std::function<OnReadSignature<int64_t>>, ::std::error_code&);
587 uint16_t, uint8_t, ::std::function<OnWriteSignature<int64_t>>);
589 uint16_t, uint8_t, ::std::function<OnWriteSignature<int64_t>>,
592 uint16_t, ::std::function<OnWriteSignature<int64_t>>);
594 uint16_t, ::std::function<OnWriteSignature<int64_t>>, ::std::error_code&);
603 uint16_t, uint8_t, ::std::function<OnReadSignature<uint64_t>>);
605 uint16_t, uint8_t, ::std::function<OnReadSignature<uint64_t>>,
608 uint16_t, ::std::function<OnReadSignature<uint64_t>>);
610 uint16_t, ::std::function<OnReadSignature<uint64_t>>, ::std::error_code&);
612 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint64_t>>);
614 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint64_t>>,
617 uint16_t, ::std::function<OnWriteSignature<uint64_t>>);
619 uint16_t, ::std::function<OnWriteSignature<uint64_t>>, ::std::error_code&);
625 ::std::lock_guard<util::BasicLockable>
lock(*
this);
626 impl_->on_life_guarding = on_life_guarding;
635 [](
co_nmt_t*
nmt,
int state,
void* data)
noexcept {
636 static_cast<Impl_*
>(data)->OnLgInd(
nmt, state);
644BasicSlave::Impl_::OnLgInd(
co_nmt_t* nmt,
int state)
noexcept {
649 self->OnLifeGuarding(occurred);
650 if (on_life_guarding) {
651 auto f = on_life_guarding;
652 util::UnlockGuard<util::BasicLockable> unlock(*self);
659BasicSlave::Impl_::Key(uint16_t idx, uint8_t subidx)
noexcept {
660 return (uint32_t(idx) << 8) | subidx;
664BasicSlave::Impl_::Key(
const co_sub_t* sub)
noexcept {
The base class for CANopen slaves.
BasicSlave(ev_exec_t *exec, io::TimerBase &timer, io::CanChannelBase &chan, const ::std::string &dcf_txt, const ::std::string &dcf_bin="", uint8_t id=0xff)
Creates a new CANopen slave.
typename::std::enable_if< is_canopen< T >::value >::type OnRead(uint16_t idx, uint8_t subidx, ::std::function< OnReadSignature< T > > ind)
Registers a callback function to be invoked on read (SDO upload) access to the specified CANopen sub-...
typename::std::enable_if< is_canopen< T >::value >::type OnWrite(uint16_t idx, uint8_t subidx, ::std::function< OnWriteSignature< T > > ind)
Registers a callback function to be invoked on write (SDO download) access to the specified CANopen s...
typename ::std::conditional< is_canopen_basic< T >::value, ::std::error_code(uint16_t idx, uint8_t subidx, T &new_val, T old_val), ::std::error_code(uint16_t idx, uint8_t subidx, T &new_val)>::type OnWriteSignature
The signature of the callback function invoked on write (SDO download) access to the local object dic...
::std::error_code(uint16_t idx, uint8_t subdx, T &value) OnReadSignature
The signature of the callback function invoked on read (SDO upload) access to the local object dictio...
void OnLifeGuarding(::std::function< void(bool)> on_life_guarding)
Registers the function to be invoked when a life guarding event occurs or is resolved.
__co_dev * dev() const noexcept
Returns a pointer to the internal CANopen device from <lely/co/dev.hpp>.
uint8_t id() const noexcept
Returns the node-ID.
Node(ev_exec_t *exec, io::TimerBase &timer, io::CanChannelBase &chan, const ::std::string &dcf_txt, const ::std::string &dcf_bin="", uint8_t id=0xff)
Creates a new CANopen node.
__co_nmt * nmt() const noexcept
Returns a pointer to the internal CANopen NMT master/slave service from <lely/co/nmt....
The type of exception thrown when an SDO abort code is received.
A reference to an abstract CAN channel.
void lock() final
Blocks until a lock can be obtained for the current execution agent (thread, process,...
A reference to an abstract timer.
This header file is part of the CANopen library; it contains the device description declarations.
co_obj_t * co_dev_find_obj(const co_dev_t *dev, co_unsigned16_t idx)
Finds an object in the object dictionary of a CANopen device.
co_unsigned8_t co_dev_get_id(const co_dev_t *dev)
Returns the node-ID of a CANopen device.
co_unsigned8_t co_dev_get_netid(const co_dev_t *dev)
Returns the network-ID of a CANopen device.
This is the internal header file of the C++ CANopen application library.
struct __co_nmt co_nmt_t
An opaque CANopen NMT master/slave service type.
struct __co_sub co_sub_t
An opaque CANopen sub-object type.
This header file is part of the CANopen library; it contains the Service Data Object (SDO) declaratio...
int co_sdo_req_dn_val(struct co_sdo_req *req, co_unsigned16_t type, void *val, co_unsigned32_t *pac)
Copies the next segment of the specified CANopen SDO download request to the internal buffer and,...
int co_sdo_req_up_val(struct co_sdo_req *req, co_unsigned16_t type, const void *val, co_unsigned32_t *pac)
Writes the specified value to a buffer and constructs a CANopen SDO upload request.
#define CO_SDO_AC_NO_DATA
SDO abort code: No data available.
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
The namespace for the C++ CANopen application library.
constexpr bool is_canopen_same(uint16_t t1, uint16_t t2) noexcept
Returns true if the CANopen data types t1 and t2 map to the same C++ type, and false if not.
@ NO_SUB
Sub-index does not exist.
@ TYPE_LEN
Data type does not match, length of service parameter does not match.
@ NO_OBJ
Object does not exist in the object dictionary.
This header file is part of the CANopen library; it contains the network management (NMT) declaration...
@ CO_NMT_EC_OCCURRED
An NMT error control event occurred.
void co_nmt_on_lg(co_nmt_t *nmt, int state)
Implements the default behavior when a life guarding event occurs (see section 7.2....
void co_nmt_set_lg_ind(co_nmt_t *nmt, co_nmt_lg_ind_t *ind, void *data)
Sets the indication function invoked when a life guarding event occurs.
This header file is part of the CANopen library; it contains the object dictionary declarations.
co_unsigned8_t co_sub_get_subidx(const co_sub_t *sub)
Returns the sub-index of a CANopen sub-object.
void co_sub_set_up_ind(co_sub_t *sub, co_sub_up_ind_t *ind, void *data)
Sets the upload indication function for a CANopen sub-object.
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
const void * co_sub_get_val(const co_sub_t *sub)
Returns a pointer to the current value of a CANopen sub-object.
void co_sub_set_dn_ind(co_sub_t *sub, co_sub_dn_ind_t *ind, void *data)
Sets the download indication function for a CANopen sub-object.
co_sub_t * co_obj_find_sub(const co_obj_t *obj, co_unsigned8_t subidx)
Finds a sub-object in a CANopen object.
int co_sub_dn(co_sub_t *sub, void *val)
Downloads (moves) a value into a CANopen sub-object if the refuse-write-on-download flag (CO_OBJ_FLAG...
co_obj_t * co_sub_get_obj(const co_sub_t *sub)
Returns the a pointer to the CANopen object containing the specified sub-object.
co_unsigned32_t co_sub_chk_val(const co_sub_t *sub, co_unsigned16_t type, const void *val)
Checks if the specifed value would be a valid value for a CANopen sub-object.
co_unsigned16_t co_sub_get_type(const co_sub_t *sub)
Returns the data type of a CANopen sub-object.
This header file is part of the C++ CANopen application library; it contains the CANopen slave declar...
A CANopen SDO upload/download request.
The internal implementation of the CANopen slave.
A class template mapping CANopen types to C and C++ types.