26#if !LELY_NO_COAPP_SLAVE
47 netid()
const noexcept {
48 return self->
dev()->getNetid();
52 return self->
dev()->getId();
55 void OnLgInd(
CONMT*
nmt,
int state)
noexcept;
63 static constexpr uint32_t Key(uint16_t idx, uint8_t subidx)
noexcept;
64 static uint32_t Key(
const COSub* sub)
noexcept;
68 ::std::map<uint32_t, ::std::function<uint32_t(
COSub*,
void*)>> dn_ind;
69 ::std::map<uint32_t, ::std::function<uint32_t(
const COSub*,
void*)>> up_ind;
73 const ::std::string& dcf_txt,
74 const ::std::string& dcf_bin, uint8_t
id)
75 :
Node(timer, bus, dcf_txt, dcf_bin, id),
78BasicSlave::~BasicSlave() =
default;
81typename ::std::enable_if<detail::IsCanopenType<T>::value>::type
85 OnRead<T>(idx, subidx, ::std::move(ind), ec);
86 if (ec)
throw SdoError(impl_->netid(), impl_->id(), idx, subidx, ec);
91template <class T, class F, uint16_t N = co_type_traits_T<T>::index>
92typename ::std::enable_if<detail::IsCanopenBasic<T>::value,
93 ::std::error_code>::type
98 return ind(sub->getObj()->getIdx(), sub->getSubidx(), val);
104template <class T, class F, uint16_t N = co_type_traits_T<T>::index>
105typename ::std::enable_if<detail::IsCanopenArray<T>::value,
106 ::std::error_code>::type
107OnUpInd(
const COSub* sub, COVal<N>& val,
const F& ind) {
112 auto ec = ind(sub->getObj()->getIdx(), sub->getSubidx(), value);
113 if (!ec) val = ::std::move(value);
123typename ::std::enable_if<detail::IsCanopenType<T>::value>::type
126 ::std::error_code& ec) {
129 auto obj =
dev()->find(idx);
135 auto sub = obj->find(subidx);
146 auto key = Impl_::Key(sub);
148 impl_->up_ind[key] = [=](
const COSub* sub,
void* p) -> uint32_t {
149 auto ec = OnUpInd<T>(sub, *
static_cast<COVal<N>*
>(p), ind);
152 sub->setUpInd<N,
Impl_, &Impl_::OnUpInd>(impl_.get());
154 if (impl_->up_ind.erase(key)) sub->setUpInd(
nullptr,
nullptr);
159typename ::std::enable_if<detail::IsCanopenType<T>::value>::type
162 ::std::error_code ec;
163 OnWrite<T>(idx, subidx, ::std::move(ind), ec);
164 if (ec)
throw SdoError(impl_->netid(), impl_->id(), idx, subidx, ec);
169template <class T, class F, uint16_t N = co_type_traits_T<T>::index>
170typename ::std::enable_if<detail::IsCanopenBasic<T>::value,
171 ::std::error_code>::type
176 return ind(sub->getObj()->getIdx(), sub->getSubidx(), val,
183template <class T, class F, uint16_t N = co_type_traits_T<T>::index>
184typename ::std::enable_if<detail::IsCanopenArray<T>::value,
185 ::std::error_code>::type
186OnDnInd(COSub* sub, COVal<N>& val,
const F& ind) {
191 auto ec = ind(sub->getObj()->getIdx(), sub->getSubidx(), value);
192 if (!ec) val = ::std::move(value);
202typename ::std::enable_if<detail::IsCanopenType<T>::value>::type
205 ::std::error_code& ec) {
208 auto obj =
dev()->find(idx);
214 auto sub = obj->find(subidx);
225 auto key = Impl_::Key(sub);
227 impl_->dn_ind[key] = [=](
COSub* sub,
void* p) -> uint32_t {
228 auto ec = OnDnInd<T>(sub, *
static_cast<COVal<N>*
>(p), ind);
231 sub->setDnInd<N,
Impl_, &Impl_::OnDnInd>(impl_.get());
233 if (impl_->dn_ind.erase(key)) sub->setDnInd(
nullptr,
nullptr);
237#ifndef DOXYGEN_SHOULD_SKIP_THIS
240template void BasicSlave::OnRead<bool>(uint16_t, uint8_t,
241 ::std::function<OnReadSignature<bool>>);
242template void BasicSlave::OnRead<bool>(uint16_t, uint8_t,
243 ::std::function<OnReadSignature<bool>>,
245template void BasicSlave::OnWrite<bool>(
246 uint16_t, uint8_t, ::std::function<OnWriteSignature<bool>>);
247template void BasicSlave::OnWrite<bool>(uint16_t, uint8_t,
248 ::std::function<OnWriteSignature<bool>>,
252template void BasicSlave::OnRead<int8_t>(
253 uint16_t, uint8_t, ::std::function<OnReadSignature<int8_t>>);
254template void BasicSlave::OnRead<int8_t>(
255 uint16_t, uint8_t, ::std::function<OnReadSignature<int8_t>>,
257template void BasicSlave::OnWrite<int8_t>(
258 uint16_t, uint8_t, ::std::function<OnWriteSignature<int8_t>>);
259template void BasicSlave::OnWrite<int8_t>(
260 uint16_t, uint8_t, ::std::function<OnWriteSignature<int8_t>>,
264template void BasicSlave::OnRead<int16_t>(
265 uint16_t, uint8_t, ::std::function<OnReadSignature<int16_t>>);
266template void BasicSlave::OnRead<int16_t>(
267 uint16_t, uint8_t, ::std::function<OnReadSignature<int16_t>>,
269template void BasicSlave::OnWrite<int16_t>(
270 uint16_t, uint8_t, ::std::function<OnWriteSignature<int16_t>>);
271template void BasicSlave::OnWrite<int16_t>(
272 uint16_t, uint8_t, ::std::function<OnWriteSignature<int16_t>>,
276template void BasicSlave::OnRead<int32_t>(
277 uint16_t, uint8_t, ::std::function<OnReadSignature<int32_t>>);
278template void BasicSlave::OnRead<int32_t>(
279 uint16_t, uint8_t, ::std::function<OnReadSignature<int32_t>>,
281template void BasicSlave::OnWrite<int32_t>(
282 uint16_t, uint8_t, ::std::function<OnWriteSignature<int32_t>>);
283template void BasicSlave::OnWrite<int32_t>(
284 uint16_t, uint8_t, ::std::function<OnWriteSignature<int32_t>>,
288template void BasicSlave::OnRead<uint8_t>(
289 uint16_t, uint8_t, ::std::function<OnReadSignature<uint8_t>>);
290template void BasicSlave::OnRead<uint8_t>(
291 uint16_t, uint8_t, ::std::function<OnReadSignature<uint8_t>>,
293template void BasicSlave::OnWrite<uint8_t>(
294 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint8_t>>);
295template void BasicSlave::OnWrite<uint8_t>(
296 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint8_t>>,
300template void BasicSlave::OnRead<uint16_t>(
301 uint16_t, uint8_t, ::std::function<OnReadSignature<uint16_t>>);
302template void BasicSlave::OnRead<uint16_t>(
303 uint16_t, uint8_t, ::std::function<OnReadSignature<uint16_t>>,
305template void BasicSlave::OnWrite<uint16_t>(
306 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint16_t>>);
307template void BasicSlave::OnWrite<uint16_t>(
308 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint16_t>>,
312template void BasicSlave::OnRead<uint32_t>(
313 uint16_t, uint8_t, ::std::function<OnReadSignature<uint32_t>>);
314template void BasicSlave::OnRead<uint32_t>(
315 uint16_t, uint8_t, ::std::function<OnReadSignature<uint32_t>>,
317template void BasicSlave::OnWrite<uint32_t>(
318 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint32_t>>);
319template void BasicSlave::OnWrite<uint32_t>(
320 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint32_t>>,
324template void BasicSlave::OnRead<float>(
325 uint16_t, uint8_t, ::std::function<OnReadSignature<float>>);
326template void BasicSlave::OnRead<float>(uint16_t, uint8_t,
327 ::std::function<OnReadSignature<float>>,
329template void BasicSlave::OnWrite<float>(
330 uint16_t, uint8_t, ::std::function<OnWriteSignature<float>>);
331template void BasicSlave::OnWrite<float>(
332 uint16_t, uint8_t, ::std::function<OnWriteSignature<float>>,
336template void BasicSlave::OnRead<::std::string>(
337 uint16_t, uint8_t, ::std::function<OnReadSignature<::std::string>>);
338template void BasicSlave::OnRead<::std::string>(
339 uint16_t, uint8_t, ::std::function<OnReadSignature<::std::string>>,
341template void BasicSlave::OnWrite<::std::string>(
342 uint16_t, uint8_t, ::std::function<OnWriteSignature<::std::string>>);
343template void BasicSlave::OnWrite<::std::string>(
344 uint16_t, uint8_t, ::std::function<OnWriteSignature<::std::string>>,
348template void BasicSlave::OnRead<::std::vector<uint8_t>>(
350 ::std::function<OnReadSignature<::std::vector<uint8_t>>>);
351template void BasicSlave::OnRead<::std::vector<uint8_t>>(
352 uint16_t, uint8_t, ::std::function<OnReadSignature<::std::vector<uint8_t>>>,
354template void BasicSlave::OnWrite<::std::vector<uint8_t>>(
356 ::std::function<OnWriteSignature<::std::vector<uint8_t>>>);
357template void BasicSlave::OnWrite<::std::vector<uint8_t>>(
359 ::std::function<OnWriteSignature<::std::vector<uint8_t>>>,
363template void BasicSlave::OnRead<::std::basic_string<char16_t>>(
365 ::std::function<OnReadSignature<::std::basic_string<char16_t>>>);
366template void BasicSlave::OnRead<::std::basic_string<char16_t>>(
368 ::std::function<OnReadSignature<::std::basic_string<char16_t>>>,
370template void BasicSlave::OnWrite<::std::basic_string<char16_t>>(
372 ::std::function<OnWriteSignature<::std::basic_string<char16_t>>>);
373template void BasicSlave::OnWrite<::std::basic_string<char16_t>>(
375 ::std::function<OnWriteSignature<::std::basic_string<char16_t>>>,
384template void BasicSlave::OnRead<double>(
385 uint16_t, uint8_t, ::std::function<OnReadSignature<double>>);
386template void BasicSlave::OnRead<double>(
387 uint16_t, uint8_t, ::std::function<OnReadSignature<double>>,
389template void BasicSlave::OnWrite<double>(
390 uint16_t, uint8_t, ::std::function<OnWriteSignature<double>>);
391template void BasicSlave::OnWrite<double>(
392 uint16_t, uint8_t, ::std::function<OnWriteSignature<double>>,
400template void BasicSlave::OnRead<int64_t>(
401 uint16_t, uint8_t, ::std::function<OnReadSignature<int64_t>>);
402template void BasicSlave::OnRead<int64_t>(
403 uint16_t, uint8_t, ::std::function<OnReadSignature<int64_t>>,
405template void BasicSlave::OnWrite<int64_t>(
406 uint16_t, uint8_t, ::std::function<OnWriteSignature<int64_t>>);
407template void BasicSlave::OnWrite<int64_t>(
408 uint16_t, uint8_t, ::std::function<OnWriteSignature<int64_t>>,
417template void BasicSlave::OnRead<uint64_t>(
418 uint16_t, uint8_t, ::std::function<OnReadSignature<uint64_t>>);
419template void BasicSlave::OnRead<uint64_t>(
420 uint16_t, uint8_t, ::std::function<OnReadSignature<uint64_t>>,
422template void BasicSlave::OnWrite<uint64_t>(
423 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint64_t>>);
424template void BasicSlave::OnWrite<uint64_t>(
425 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint64_t>>,
431 nmt->setLgInd<Impl_, &Impl_::OnLgInd>(
this);
435BasicSlave::Impl_::OnLgInd(
CONMT* nmt,
int state)
noexcept {
444BasicSlave::Impl_::OnDnInd(COSub* sub, COVal<N>& val)
noexcept {
445 auto it = dn_ind.find(Key(sub));
446 if (it == dn_ind.end())
return 0;
447 return it->second(sub,
static_cast<void*
>(&val));
452BasicSlave::Impl_::OnUpInd(
const COSub* sub, COVal<N>& val)
noexcept {
453 auto it = up_ind.find(Key(sub));
454 if (it == up_ind.end())
return 0;
455 return it->second(sub,
static_cast<void*
>(&val));
459BasicSlave::Impl_::Key(uint16_t idx, uint8_t subidx)
noexcept {
460 return (uint32_t(idx) << 8) | subidx;
464BasicSlave::Impl_::Key(
const COSub* sub)
noexcept {
467 return Key(sub->getObj()->getIdx(), sub->getSubidx());
An opaque CANopen NMT master/slave service type.
An opaque CANopen sub-object type.
The base class for CANopen slaves.
BasicSlave(aio::TimerBase &timer, aio::CanBusBase &bus, const ::std::string &dcf_txt, const ::std::string &dcf_bin="", uint8_t id=0xff)
Creates a new CANopen slave.
typename ::std::conditional< detail::IsCanopenBasic< 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...
typename::std::enable_if< detail::IsCanopenType< 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::enable_if< detail::IsCanopenType< 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-...
CODev * dev() const noexcept
Returns a pointer to the internal CANopen device from <lely/co/dev.hpp>.
The base class for CANopen nodes.
CONMT * 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.
This header file is part of the CANopen library; it contains the C++ interface of the device descript...
bool IsCanopenSame(uint16_t t1, uint16_t t2)
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.
Global namespace for the Lely Industries N.V. libraries.
@ CO_NMT_EC_OCCURRED
An NMT error control event occurred.
This header file is part of the CANopen library; it contains the C++ interface of the network managem...
This header file is part of the CANopen library; it contains the C++ interface of the object dictiona...
This header file is part of the C++ CANopen application library; it contains the CANopen slave declar...
This is the internal header file of the C++ CANopen application library.
The internal implementation of the CANopen slave.
A class template mapping CANopen types to C++ types.