39 Impl_(const ::std::string& dcf_txt, const ::std::string& dcf_bin, uint8_t
id,
44 if (mutex) mutex->
lock();
48 if (mutex) mutex->
unlock();
52 netid() const noexcept {
53 return dev->getNetid();
60 void Set(uint16_t idx, uint8_t subidx, const ::std::string& value,
61 ::std::error_code& ec);
63 void Set(uint16_t idx, uint8_t subidx, const ::std::vector<uint8_t>& value,
64 ::std::error_code& ec);
66 void Set(uint16_t idx, uint8_t subidx,
67 const ::std::basic_string<char16_t>& value, ::std::error_code& ec);
70 void Set(uint16_t idx, uint8_t subidx,
const void* p, ::std::size_t n,
71 ::std::error_code& ec);
73 BasicLockable* mutex{
nullptr};
75 unique_c_ptr<CODev> dev;
80 : impl_(new
Impl_(dcf_txt, dcf_bin, id, mutex)) {}
84Device::~Device() =
default;
88 ::std::lock_guard<Impl_> lock(*impl_);
90 return impl_->netid();
95 ::std::lock_guard<Impl_> lock(*impl_);
103OnDnCon(
COCSDO*, uint16_t, uint8_t, uint32_t ac,
void* data)
noexcept {
104 *
static_cast<uint32_t*
>(data) = ac;
109OnUpCon(
COCSDO*, uint16_t, uint8_t, uint32_t ac, T value,
void* data)
noexcept {
110 auto* t =
static_cast<decltype(::std::tie(ac, value))*
>(data);
111 *t = ::std::forward_as_tuple(ac, ::std::move(value));
117typename ::std::enable_if<detail::IsCanopenType<T>::value, T>::type
119 ::std::error_code ec;
120 T value(Read<T>(idx, subidx, ec));
121 if (ec)
throw SdoError(
netid(),
id(), idx, subidx, ec,
"Read");
126typename ::std::enable_if<detail::IsCanopenType<T>::value, T>::type
127Device::Read(uint16_t idx, uint8_t subidx, ::std::error_code& ec)
const {
130 auto t = ::std::tie(ac, value);
132 ::std::lock_guard<Impl_> lock(*impl_);
133 if (upReq<T, &OnUpCon<T>>(*impl_->dev, idx, subidx, &t) == -1)
144typename ::std::enable_if<detail::IsCanopenBasic<T>::value>::type
146 ::std::error_code ec;
147 Write(idx, subidx, value, ec);
148 if (ec)
throw SdoError(
netid(),
id(), idx, subidx, ec,
"Write");
152typename ::std::enable_if<detail::IsCanopenBasic<T>::value>::type
153Device::Write(uint16_t idx, uint8_t subidx, T value, ::std::error_code& ec) {
157 ::std::lock_guard<Impl_> lock(*impl_);
158 if (dnReq<N>(*impl_->dev, idx, subidx, value, &OnDnCon, &ac) == -1)
168typename ::std::enable_if<detail::IsCanopenArray<T>::value>::type
170 ::std::error_code ec;
171 Write(idx, subidx, value, ec);
172 if (ec)
throw SdoError(
netid(),
id(), idx, subidx, ec,
"Write");
176typename ::std::enable_if<detail::IsCanopenArray<T>::value>::type
178 ::std::error_code& ec) {
182 ::std::lock_guard<Impl_> lock(*impl_);
183 if (dnReq<N>(*impl_->dev, idx, subidx, value, &OnDnCon, &ac) == -1)
192#ifndef DOXYGEN_SHOULD_SKIP_THIS
195template bool Device::Read<bool>(uint16_t, uint8_t)
const;
196template bool Device::Read<bool>(uint16_t, uint8_t, ::std::error_code&)
const;
197template void Device::Write<bool>(uint16_t, uint8_t,
bool);
198template void Device::Write<bool>(uint16_t, uint8_t,
bool, ::std::error_code&);
201template int8_t Device::Read<int8_t>(uint16_t, uint8_t)
const;
202template int8_t Device::Read<int8_t>(uint16_t, uint8_t,
203 ::std::error_code&)
const;
204template void Device::Write<int8_t>(uint16_t, uint8_t, int8_t);
205template void Device::Write<int8_t>(uint16_t, uint8_t, int8_t,
209template int16_t Device::Read<int16_t>(uint16_t, uint8_t)
const;
210template int16_t Device::Read<int16_t>(uint16_t, uint8_t,
211 ::std::error_code&)
const;
212template void Device::Write<int16_t>(uint16_t, uint8_t, int16_t);
213template void Device::Write<int16_t>(uint16_t, uint8_t, int16_t,
217template int32_t Device::Read<int32_t>(uint16_t, uint8_t)
const;
218template int32_t Device::Read<int32_t>(uint16_t, uint8_t,
219 ::std::error_code&)
const;
220template void Device::Write<int32_t>(uint16_t, uint8_t, int32_t);
221template void Device::Write<int32_t>(uint16_t, uint8_t, int32_t,
225template uint8_t Device::Read<uint8_t>(uint16_t, uint8_t)
const;
226template uint8_t Device::Read<uint8_t>(uint16_t, uint8_t,
227 ::std::error_code&)
const;
228template void Device::Write<uint8_t>(uint16_t, uint8_t, uint8_t);
229template void Device::Write<uint8_t>(uint16_t, uint8_t, uint8_t,
233template uint16_t Device::Read<uint16_t>(uint16_t, uint8_t)
const;
234template uint16_t Device::Read<uint16_t>(uint16_t, uint8_t,
235 ::std::error_code&)
const;
236template void Device::Write<uint16_t>(uint16_t, uint8_t, uint16_t);
237template void Device::Write<uint16_t>(uint16_t, uint8_t, uint16_t,
241template uint32_t Device::Read<uint32_t>(uint16_t, uint8_t)
const;
242template uint32_t Device::Read<uint32_t>(uint16_t, uint8_t,
243 ::std::error_code&)
const;
244template void Device::Write<uint32_t>(uint16_t, uint8_t, uint32_t);
245template void Device::Write<uint32_t>(uint16_t, uint8_t, uint32_t,
249template float Device::Read<float>(uint16_t, uint8_t)
const;
250template float Device::Read<float>(uint16_t, uint8_t, ::std::error_code&)
const;
251template void Device::Write<float>(uint16_t, uint8_t,
float);
252template void Device::Write<float>(uint16_t, uint8_t,
float,
256template ::std::string Device::Read<::std::string>(uint16_t, uint8_t)
const;
257template ::std::string Device::Read<::std::string>(uint16_t, uint8_t,
258 ::std::error_code&)
const;
259template void Device::Write<::std::string>(uint16_t, uint8_t,
260 const ::std::string&);
261template void Device::Write<::std::string>(uint16_t, uint8_t,
262 const ::std::string&,
266template ::std::vector<uint8_t> Device::Read<::std::vector<uint8_t>>(
267 uint16_t, uint8_t)
const;
268template ::std::vector<uint8_t> Device::Read<::std::vector<uint8_t>>(
269 uint16_t, uint8_t, ::std::error_code&)
const;
270template void Device::Write<::std::vector<uint8_t>>(
271 uint16_t, uint8_t, const ::std::vector<uint8_t>&);
272template void Device::Write<::std::vector<uint8_t>>(
273 uint16_t, uint8_t, const ::std::vector<uint8_t>&, ::std::error_code&);
276template ::std::basic_string<char16_t>
277 Device::Read<::std::basic_string<char16_t>>(uint16_t, uint8_t)
const;
278template ::std::basic_string<char16_t>
279Device::Read<::std::basic_string<char16_t>>(uint16_t, uint8_t,
280 ::std::error_code&)
const;
281template void Device::Write<::std::basic_string<char16_t>>(
282 uint16_t, uint8_t, const ::std::basic_string<char16_t>&);
283template void Device::Write<::std::basic_string<char16_t>>(
284 uint16_t, uint8_t, const ::std::basic_string<char16_t>&,
293template double Device::Read<double>(uint16_t, uint8_t)
const;
294template double Device::Read<double>(uint16_t, uint8_t,
295 ::std::error_code&)
const;
296template void Device::Write<double>(uint16_t, uint8_t,
double);
297template void Device::Write<double>(uint16_t, uint8_t,
double,
305template int64_t Device::Read<int64_t>(uint16_t, uint8_t)
const;
306template int64_t Device::Read<int64_t>(uint16_t, uint8_t,
307 ::std::error_code&)
const;
308template void Device::Write<int64_t>(uint16_t, uint8_t, int64_t);
309template void Device::Write<int64_t>(uint16_t, uint8_t, int64_t,
318template uint64_t Device::Read<uint64_t>(uint16_t, uint8_t)
const;
319template uint64_t Device::Read<uint64_t>(uint16_t, uint8_t,
320 ::std::error_code&)
const;
321template void Device::Write<uint64_t>(uint16_t, uint8_t, uint64_t);
322template void Device::Write<uint64_t>(uint16_t, uint8_t, uint64_t,
329 ::std::error_code ec;
330 Write(idx, subidx, value, ec);
331 if (ec)
throw SdoError(
netid(),
id(), idx, subidx, ec,
"Write");
336 ::std::error_code& ec) {
337 Write(idx, subidx, value, ::std::char_traits<char>::length(value), ec);
342 ::std::error_code ec;
343 Write(idx, subidx, value, ec);
344 if (ec)
throw SdoError(
netid(),
id(), idx, subidx, ec,
"Write");
349 ::std::error_code& ec) {
353 ::std::lock_guard<Impl_> lock(*impl_);
355 if (dnReq<N>(*impl_->dev, idx, subidx, value, &OnDnCon, &ac) == -1)
365Device::Write(uint16_t idx, uint8_t subidx,
const void* p, ::std::size_t n) {
366 ::std::error_code ec;
367 Write(idx, subidx, p, n, ec);
368 if (ec)
throw SdoError(
netid(),
id(), idx, subidx, ec,
"Write");
373 ::std::error_code& ec) {
376 ::std::lock_guard<Impl_> lock(*impl_);
377 if (dnReq(*impl_->dev, idx, subidx, p, n, &OnDnCon, &ac) == -1)
388 return impl_->dev.get();
391const ::std::type_info&
393 ::std::error_code ec;
394 auto& ti =
Type(idx, subidx, ec);
395 if (ec)
throw SdoError(impl_->netid(), impl_->id(), idx, subidx, ec,
"Type");
399const ::std::type_info&
400Device::Type(uint16_t idx, uint8_t subidx, ::std::error_code& ec)
const {
401 auto obj = impl_->dev->find(idx);
407 auto sub = obj->find(subidx);
414 switch (sub->getType()) {
418 return typeid(int8_t);
420 return typeid(int16_t);
422 return typeid(int32_t);
424 return typeid(uint8_t);
426 return typeid(uint16_t);
428 return typeid(uint32_t);
430 return typeid(float);
432 return typeid(::std::string);
434 return typeid(::std::vector<uint8_t>);
436 return typeid(::std::basic_string<char16_t>);
440 return typeid(::std::vector<uint8_t>);
443 return typeid(double);
448 return typeid(int64_t);
454 return typeid(uint64_t);
461typename ::std::enable_if<detail::IsCanopenType<T>::value, T>::type
463 ::std::error_code ec;
464 auto value = Get<T>(idx, subidx, ec);
465 if (ec)
throw SdoError(impl_->netid(), impl_->id(), idx, subidx, ec,
"Get");
470typename ::std::enable_if<detail::IsCanopenType<T>::value, T>::type
471Device::Get(uint16_t idx, uint8_t subidx, ::std::error_code& ec)
const {
474 auto obj = impl_->dev->find(idx);
480 auto sub = obj->find(subidx);
494 return sub->getVal<N>();
498typename ::std::enable_if<detail::IsCanopenBasic<T>::value>::type
500 ::std::error_code ec;
501 Set(idx, subidx, value, ec);
502 if (ec)
throw SdoError(impl_->netid(), impl_->id(), idx, subidx, ec,
"Set");
506typename ::std::enable_if<detail::IsCanopenBasic<T>::value>::type
507Device::Set(uint16_t idx, uint8_t subidx, T value, ::std::error_code& ec) {
510 impl_->Set<N>(idx, subidx, &value,
sizeof(value), ec);
514typename ::std::enable_if<detail::IsCanopenArray<T>::value>::type
516 ::std::error_code ec;
517 Set(idx, subidx, value, ec);
518 if (ec)
throw SdoError(impl_->netid(), impl_->id(), idx, subidx, ec,
"Set");
522typename ::std::enable_if<detail::IsCanopenArray<T>::value>::type
524 ::std::error_code& ec) {
525 impl_->Set(idx, subidx, value, ec);
528#ifndef DOXYGEN_SHOULD_SKIP_THIS
531template bool Device::Get<bool>(uint16_t, uint8_t)
const;
532template bool Device::Get<bool>(uint16_t, uint8_t, ::std::error_code&)
const;
533template void Device::Set<bool>(uint16_t, uint8_t,
bool);
534template void Device::Set<bool>(uint16_t, uint8_t,
bool, ::std::error_code&);
537template int8_t Device::Get<int8_t>(uint16_t, uint8_t)
const;
538template int8_t Device::Get<int8_t>(uint16_t, uint8_t,
539 ::std::error_code&)
const;
540template void Device::Set<int8_t>(uint16_t, uint8_t, int8_t);
541template void Device::Set<int8_t>(uint16_t, uint8_t, int8_t,
545template int16_t Device::Get<int16_t>(uint16_t, uint8_t)
const;
546template int16_t Device::Get<int16_t>(uint16_t, uint8_t,
547 ::std::error_code&)
const;
548template void Device::Set<int16_t>(uint16_t, uint8_t, int16_t);
549template void Device::Set<int16_t>(uint16_t, uint8_t, int16_t,
553template int32_t Device::Get<int32_t>(uint16_t, uint8_t)
const;
554template int32_t Device::Get<int32_t>(uint16_t, uint8_t,
555 ::std::error_code&)
const;
556template void Device::Set<int32_t>(uint16_t, uint8_t, int32_t);
557template void Device::Set<int32_t>(uint16_t, uint8_t, int32_t,
561template uint8_t Device::Get<uint8_t>(uint16_t, uint8_t)
const;
562template uint8_t Device::Get<uint8_t>(uint16_t, uint8_t,
563 ::std::error_code&)
const;
564template void Device::Set<uint8_t>(uint16_t, uint8_t, uint8_t);
565template void Device::Set<uint8_t>(uint16_t, uint8_t, uint8_t,
569template uint16_t Device::Get<uint16_t>(uint16_t, uint8_t)
const;
570template uint16_t Device::Get<uint16_t>(uint16_t, uint8_t,
571 ::std::error_code&)
const;
572template void Device::Set<uint16_t>(uint16_t, uint8_t, uint16_t);
573template void Device::Set<uint16_t>(uint16_t, uint8_t, uint16_t,
577template uint32_t Device::Get<uint32_t>(uint16_t, uint8_t)
const;
578template uint32_t Device::Get<uint32_t>(uint16_t, uint8_t,
579 ::std::error_code&)
const;
580template void Device::Set<uint32_t>(uint16_t, uint8_t, uint32_t);
581template void Device::Set<uint32_t>(uint16_t, uint8_t, uint32_t,
585template float Device::Get<float>(uint16_t, uint8_t)
const;
586template float Device::Get<float>(uint16_t, uint8_t, ::std::error_code&)
const;
587template void Device::Set<float>(uint16_t, uint8_t,
float);
588template void Device::Set<float>(uint16_t, uint8_t,
float, ::std::error_code&);
591template ::std::string Device::Get<::std::string>(uint16_t, uint8_t)
const;
592template ::std::string Device::Get<::std::string>(uint16_t, uint8_t,
593 ::std::error_code&)
const;
594template void Device::Set<::std::string>(uint16_t, uint8_t,
595 const ::std::string&);
596template void Device::Set<::std::string>(uint16_t, uint8_t,
597 const ::std::string&,
601template ::std::vector<uint8_t> Device::Get<::std::vector<uint8_t>>(
602 uint16_t, uint8_t)
const;
603template ::std::vector<uint8_t> Device::Get<::std::vector<uint8_t>>(
604 uint16_t, uint8_t, ::std::error_code&)
const;
605template void Device::Set<::std::vector<uint8_t>>(
606 uint16_t, uint8_t, const ::std::vector<uint8_t>&);
607template void Device::Set<::std::vector<uint8_t>>(uint16_t, uint8_t,
608 const ::std::vector<uint8_t>&,
612template ::std::basic_string<char16_t>
613 Device::Get<::std::basic_string<char16_t>>(uint16_t, uint8_t)
const;
614template ::std::basic_string<char16_t>
615Device::Get<::std::basic_string<char16_t>>(uint16_t, uint8_t,
616 ::std::error_code&)
const;
617template void Device::Set<::std::basic_string<char16_t>>(
618 uint16_t, uint8_t, const ::std::basic_string<char16_t>&);
619template void Device::Set<::std::basic_string<char16_t>>(
620 uint16_t, uint8_t, const ::std::basic_string<char16_t>&,
629template double Device::Get<double>(uint16_t, uint8_t)
const;
630template double Device::Get<double>(uint16_t, uint8_t,
631 ::std::error_code&)
const;
632template void Device::Set<double>(uint16_t, uint8_t,
double);
633template void Device::Set<double>(uint16_t, uint8_t,
double,
641template int64_t Device::Get<int64_t>(uint16_t, uint8_t)
const;
642template int64_t Device::Get<int64_t>(uint16_t, uint8_t,
643 ::std::error_code&)
const;
644template void Device::Set<int64_t>(uint16_t, uint8_t, int64_t);
645template void Device::Set<int64_t>(uint16_t, uint8_t, int64_t,
654template uint64_t Device::Get<uint64_t>(uint16_t, uint8_t)
const;
655template uint64_t Device::Get<uint64_t>(uint16_t, uint8_t,
656 ::std::error_code&)
const;
657template void Device::Set<uint64_t>(uint16_t, uint8_t, uint64_t);
658template void Device::Set<uint64_t>(uint16_t, uint8_t, uint64_t,
665 ::std::error_code ec;
666 Set(idx, subidx, value, ec);
667 if (ec)
throw SdoError(impl_->netid(), impl_->id(), idx, subidx, ec,
"Set");
672 ::std::error_code& ec) {
678 ::std::error_code ec;
679 Set(idx, subidx, value, ec);
680 if (ec)
throw SdoError(impl_->netid(), impl_->id(), idx, subidx, ec,
"Set");
685 ::std::error_code& ec) {
690Device::Set(uint16_t idx, uint8_t subidx,
const void* p, ::std::size_t n) {
691 ::std::error_code ec;
692 Set(idx, subidx, p, n, ec);
693 if (ec)
throw SdoError(impl_->netid(), impl_->id(), idx, subidx, ec,
"Set");
697Device::Set(uint16_t idx, uint8_t subidx,
const void* p, ::std::size_t n,
698 ::std::error_code& ec) {
702Device::Impl_::Impl_(const ::std::string& dcf_txt, const ::std::string& dcf_bin,
705 if (!dcf_bin.empty() &&
dev->readDCF(
nullptr,
nullptr, dcf_bin.c_str()) == -1)
706 throw_errc(
"Device");
708 if (
id != 0xff &&
dev->setId(
id) == -1) throw_errc(
"Device");
712Device::Impl_::Set(uint16_t idx, uint8_t subidx, const ::std::string& value,
713 ::std::error_code& ec) {
714 Set<CO_DEFTYPE_VISIBLE_STRING>(idx, subidx, value.c_str(), 0, ec);
718Device::Impl_::Set(uint16_t idx, uint8_t subidx,
719 const ::std::vector<uint8_t>& value, ::std::error_code& ec) {
720 Set<CO_DEFTYPE_OCTET_STRING>(idx, subidx, value.data(), value.size(), ec);
724Device::Impl_::Set(uint16_t idx, uint8_t subidx,
725 const ::std::basic_string<char16_t>& value,
726 ::std::error_code& ec) {
727 Set<CO_DEFTYPE_UNICODE_STRING>(idx, subidx, value.c_str(), 0, ec);
732Device::Impl_::Set(uint16_t idx, uint8_t subidx,
const void* p, ::std::size_t n,
733 ::std::error_code& ec) {
734 auto obj =
dev->find(idx);
740 auto sub = obj->find(subidx);
An opaque CANopen Client-SDO service type.
An opaque CANopen device type.
An abstract interface conforming to the BasicLockable concept.
virtual void unlock()=0
Releases the lock held by the execution agent. Throws no exceptions.
virtual void lock()=0
Blocks until a lock can be obtained for the current execution agent (thread, process,...
The CANopen device description.
uint8_t netid() const noexcept
Returns the network-ID.
typename::std::enable_if< detail::IsCanopenType< T >::value, T >::type Get(uint16_t idx, uint8_t subidx) const
Reads the value of a sub-object.
Device(const ::std::string &dcf_txt, const ::std::string &dcf_bin="", uint8_t id=0xff, BasicLockable *mutex=nullptr)
Creates a new CANopen device description.
typename::std::enable_if< detail::IsCanopenType< T >::value, T >::type Read(uint16_t idx, uint8_t subidx) const
Submits an SDO upload request to the local object dictionary.
const ::std::type_info & Type(uint16_t idx, uint8_t subidx) const
Returns the type of a sub-object.
CODev * dev() const noexcept
Returns a pointer to the internal CANopen device from <lely/co/dev.hpp>.
typename::std::enable_if< detail::IsCanopenBasic< T >::value >::type Set(uint16_t idx, uint8_t subidx, T value)
Writes a CANopen basic value to a sub-object.
typename::std::enable_if< detail::IsCanopenBasic< T >::value >::type Write(uint16_t idx, uint8_t subidx, T value)
Submits an SDO download request to the local object dictionary.
uint8_t id() const noexcept
Returns the node-ID.
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 Client-SDO decl...
This header file is part of the CANopen library; it contains the C++ interface of the Electronic Data...
This header file is part of the C++ CANopen application library; it contains the CANopen device descr...
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.
SdoErrc
The SDO abort codes.
@ 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.
unique_c_ptr< T > make_unique_c(Args &&... args)
Creates an instance of a trivial, standard layout or incomplete C type and wraps it in a lely::unique...
This header file is part of the CANopen library; it contains the C++ interface of the object dictiona...
This is the internal header file of the C++ CANopen application library.
The internal implementation of the CANopen device description.
virtual void lock() override
Blocks until a lock can be obtained for the current execution agent (thread, process,...
virtual void unlock() override
Releases the lock held by the execution agent. Throws no exceptions.
A class template mapping CANopen types to C++ types.
#define CO_DEFTYPE_UNICODE_STRING
The data type (and object index) of an array of (16-bit) Unicode characters.
#define CO_DEFTYPE_UNSIGNED16
The data type (and object index) of a 16-bit unsigned integer.
#define CO_DEFTYPE_VISIBLE_STRING
The data type (and object index) of an array of visible characters.
#define CO_DEFTYPE_UNSIGNED64
The data type (and object index) of a 64-bit unsigned integer.
#define CO_DEFTYPE_INTEGER8
The data type (and object index) of an 8-bit signed integer.
#define CO_DEFTYPE_DOMAIN
The data type (and object index) of an arbitrary large block of data.
#define CO_DEFTYPE_UNSIGNED8
The data type (and object index) of an 8-bit unsigned integer.
#define CO_DEFTYPE_REAL64
The data type (and object index) of a 64-bit IEEE-754 floating-point number.
#define CO_DEFTYPE_BOOLEAN
The data type (and object index) of a boolean truth value.
#define CO_DEFTYPE_INTEGER32
The data type (and object index) of a 32-bit signed integer.
#define CO_DEFTYPE_INTEGER64
The data type (and object index) of a 64-bit signed integer.
#define CO_DEFTYPE_UNSIGNED32
The data type (and object index) of a 32-bit unsigned integer.
#define CO_DEFTYPE_INTEGER16
The data type (and object index) of a 16-bit signed integer.
#define CO_DEFTYPE_OCTET_STRING
The data type (and object index) of an array of octets.
#define CO_DEFTYPE_REAL32
The data type (and object index) of a 32-bit IEEE-754 floating-point number.