34#if !LELY_NO_CO_RPDO && !LELY_NO_CO_MPDO
39#if !LELY_NO_CO_RPDO && !LELY_NO_CO_MPDO
42#if !LELY_NO_CO_RPDO || !LELY_NO_CO_TPDO
59 operator()(
co_dev_t* dev)
const noexcept {
68 virtual ~Impl_() =
default;
72 if (mutex) mutex->lock();
77 if (mutex) mutex->unlock();
92 ::std::tuple<uint16_t, uint8_t>
94 ::std::error_code& ec)
const noexcept {
97 auto it = rpdo_mapping.find((
static_cast<uint32_t>(
id) << 24) |
98 (
static_cast<uint32_t>(idx) << 8) | subidx);
99 if (
it != rpdo_mapping.end()) {
100 idx = (
it->second >> 8) & 0xffff;
101 subidx =
it->second & 0xff;
111 return ::std::make_tuple(idx, subidx);
114 ::std::tuple<uint8_t, uint16_t, uint8_t>
115 RpdoMapping(uint16_t idx, uint8_t subidx,
116 ::std::error_code& ec)
const noexcept {
119 auto it = rpdo_mapping.find((
static_cast<uint32_t
>(idx) << 8) | subidx);
120 if (it != rpdo_mapping.end()) {
121 id = (it->second >> 24) & 0xff;
122 idx = (it->second >> 8) & 0xffff;
123 subidx = it->second & 0xff;
133 return ::std::make_tuple(
id, idx, subidx);
136 ::std::tuple<uint16_t, uint8_t>
137 TpdoMapping(uint8_t
id, uint16_t idx, uint8_t subidx,
138 ::std::error_code& ec)
const noexcept {
141 auto it = tpdo_mapping.find((
static_cast<uint32_t
>(
id) << 24) |
142 (
static_cast<uint32_t
>(idx) << 8) | subidx);
143 if (it != tpdo_mapping.end()) {
144 idx = (it->second >> 8) & 0xffff;
145 subidx = it->second & 0xff;
155 return ::std::make_tuple(idx, subidx);
160 BasicLockable* mutex{
nullptr};
162 ::std::unique_ptr<co_dev_t, DeviceDeleter> dev;
165 ::std::map<uint32_t, uint32_t> rpdo_mapping;
168 ::std::map<uint32_t, uint32_t> tpdo_mapping;
171 ::std::function<void(uint16_t, uint8_t)> on_write;
173 ::std::function<void(uint8_t, uint16_t, uint8_t)> on_rpdo_write;
183Device::~Device() =
default;
187 ::std::lock_guard<Impl_> lock(*impl_);
189 return impl_->netid();
194 ::std::lock_guard<Impl_> lock(*impl_);
209 void* data)
noexcept {
211 using c_type =
typename traits::c_type;
213 auto t =
static_cast<::std::tuple<uint32_t&, T&>*
>(data);
217 ::std::error_code ec;
218 val = traits::construct(ptr, n, ec);
222 *t = ::std::forward_as_tuple(ac, traits::from_c_type(val));
224 traits::destroy(val);
230typename ::std::enable_if<is_canopen<T>::value, T>::type
232 ::std::error_code ec;
233 T value(
Read<T>(idx, subidx, ec));
239typename ::std::enable_if<is_canopen<T>::value, T>::type
243 auto t = ::std::tie(ac, value);
245 ::std::lock_guard<Impl_> lock(*impl_);
254 ec = util::make_error_code();
261typename ::std::enable_if<is_canopen<T>::value>::type
263 ::std::error_code ec;
264 Write(idx, subidx, value, ec);
269typename ::std::enable_if<is_canopen<T>::value>::type
271 ::std::error_code& ec) {
274 auto val = traits::to_c_type(value, ec);
279 ::std::lock_guard<Impl_> lock(*impl_);
289 ec = util::make_error_code();
294 traits::destroy(val);
300 ::std::error_code& ec) {
301 Write(idx, subidx, value.c_str(), ec);
307 ::std::error_code& ec) {
308 Write(idx, subidx, value.data(), value.size(), ec);
311#ifndef DOXYGEN_SHOULD_SKIP_THIS
314template bool Device::Read<bool>(uint16_t, uint8_t)
const;
315template bool Device::Read<bool>(uint16_t, uint8_t, ::std::error_code&)
const;
316template void Device::Write<bool>(uint16_t, uint8_t,
const bool&);
317template void Device::Write<bool>(uint16_t, uint8_t,
const bool&,
321template int8_t Device::Read<int8_t>(uint16_t, uint8_t)
const;
322template int8_t Device::Read<int8_t>(uint16_t, uint8_t,
323 ::std::error_code&)
const;
324template void Device::Write<int8_t>(uint16_t, uint8_t,
const int8_t&);
325template void Device::Write<int8_t>(uint16_t, uint8_t,
const int8_t&,
329template int16_t Device::Read<int16_t>(uint16_t, uint8_t)
const;
330template int16_t Device::Read<int16_t>(uint16_t, uint8_t,
331 ::std::error_code&)
const;
332template void Device::Write<int16_t>(uint16_t, uint8_t,
const int16_t&);
333template void Device::Write<int16_t>(uint16_t, uint8_t,
const int16_t&,
337template int32_t Device::Read<int32_t>(uint16_t, uint8_t)
const;
338template int32_t Device::Read<int32_t>(uint16_t, uint8_t,
339 ::std::error_code&)
const;
340template void Device::Write<int32_t>(uint16_t, uint8_t,
const int32_t&);
341template void Device::Write<int32_t>(uint16_t, uint8_t,
const int32_t&,
345template uint8_t Device::Read<uint8_t>(uint16_t, uint8_t)
const;
346template uint8_t Device::Read<uint8_t>(uint16_t, uint8_t,
347 ::std::error_code&)
const;
348template void Device::Write<uint8_t>(uint16_t, uint8_t,
const uint8_t&);
349template void Device::Write<uint8_t>(uint16_t, uint8_t,
const uint8_t&,
353template uint16_t Device::Read<uint16_t>(uint16_t, uint8_t)
const;
354template uint16_t Device::Read<uint16_t>(uint16_t, uint8_t,
355 ::std::error_code&)
const;
356template void Device::Write<uint16_t>(uint16_t, uint8_t,
const uint16_t&);
357template void Device::Write<uint16_t>(uint16_t, uint8_t,
const uint16_t&,
361template uint32_t Device::Read<uint32_t>(uint16_t, uint8_t)
const;
362template uint32_t Device::Read<uint32_t>(uint16_t, uint8_t,
363 ::std::error_code&)
const;
364template void Device::Write<uint32_t>(uint16_t, uint8_t,
const uint32_t&);
365template void Device::Write<uint32_t>(uint16_t, uint8_t,
const uint32_t&,
369template float Device::Read<float>(uint16_t, uint8_t)
const;
370template float Device::Read<float>(uint16_t, uint8_t, ::std::error_code&)
const;
371template void Device::Write<float>(uint16_t, uint8_t,
const float&);
372template void Device::Write<float>(uint16_t, uint8_t,
const float&,
376template ::std::string Device::Read<::std::string>(uint16_t, uint8_t)
const;
377template ::std::string Device::Read<::std::string>(uint16_t, uint8_t,
378 ::std::error_code&)
const;
379template void Device::Write<::std::string>(uint16_t, uint8_t,
380 const ::std::string&);
386template ::std::vector<uint8_t> Device::Read<::std::vector<uint8_t>>(
387 uint16_t, uint8_t)
const;
388template ::std::vector<uint8_t> Device::Read<::std::vector<uint8_t>>(
389 uint16_t, uint8_t, ::std::error_code&)
const;
390template void Device::Write<::std::vector<uint8_t>>(
391 uint16_t, uint8_t, const ::std::vector<uint8_t>&);
396template ::std::basic_string<char16_t>
397 Device::Read<::std::basic_string<char16_t>>(uint16_t, uint8_t)
const;
398template ::std::basic_string<char16_t>
399Device::Read<::std::basic_string<char16_t>>(uint16_t, uint8_t,
400 ::std::error_code&)
const;
401template void Device::Write<::std::basic_string<char16_t>>(
402 uint16_t, uint8_t, const ::std::basic_string<char16_t>&);
403template void Device::Write<::std::basic_string<char16_t>>(
404 uint16_t, uint8_t, const ::std::basic_string<char16_t>&,
413template double Device::Read<double>(uint16_t, uint8_t)
const;
414template double Device::Read<double>(uint16_t, uint8_t,
415 ::std::error_code&)
const;
416template void Device::Write<double>(uint16_t, uint8_t,
const double&);
417template void Device::Write<double>(uint16_t, uint8_t,
const double&,
425template int64_t Device::Read<int64_t>(uint16_t, uint8_t)
const;
426template int64_t Device::Read<int64_t>(uint16_t, uint8_t,
427 ::std::error_code&)
const;
428template void Device::Write<int64_t>(uint16_t, uint8_t,
const int64_t&);
429template void Device::Write<int64_t>(uint16_t, uint8_t,
const int64_t&,
438template uint64_t Device::Read<uint64_t>(uint16_t, uint8_t)
const;
439template uint64_t Device::Read<uint64_t>(uint16_t, uint8_t,
440 ::std::error_code&)
const;
441template void Device::Write<uint64_t>(uint16_t, uint8_t,
const uint64_t&);
442template void Device::Write<uint64_t>(uint16_t, uint8_t,
const uint64_t&,
449 ::std::error_code ec;
450 Write(idx, subidx, value, ec);
456 ::std::error_code& ec) {
457 Write(idx, subidx, value, ::std::char_traits<char>::length(value), ec);
462 ::std::error_code ec;
463 Write(idx, subidx, value, ec);
469 ::std::error_code& ec) {
472 auto val = traits::to_c_type(value, ec);
477 ::std::lock_guard<Impl_> lock(*impl_);
487 ec = util::make_error_code();
492 traits::destroy(val);
497 ::std::error_code ec;
498 Write(idx, subidx, p, n, ec);
504 ::std::error_code& ec) {
507 ::std::lock_guard<Impl_> lock(*impl_);
516 ec = util::make_error_code();
523 ::std::error_code ec;
530 ::std::error_code& ec) {
533 ::std::lock_guard<Impl_> lock(*impl_);
542 ec = util::make_error_code();
549 ::std::error_code ec;
567 ec = util::make_error_code();
576 ::std::error_code ec;
583 ::std::error_code& ec)
noexcept {
584 ::std::lock_guard<Impl_> lock(*impl_);
586 SetEvent(idx, subidx, ec);
590typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
592 ::std::error_code ec;
599typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
601 ::std::error_code& ec)
const {
604 ::std::lock_guard<Impl_> lock(*impl_);
605 ::std::tie(idx, subidx) = impl_->RpdoMapping(
id, idx, subidx, ec);
608 return Read<T>(idx, subidx, ec);
612typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
614 ::std::error_code ec;
621typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
623 ::std::error_code& ec)
const {
626 ::std::lock_guard<Impl_> lock(*impl_);
627 ::std::tie(idx, subidx) = impl_->TpdoMapping(
id, idx, subidx, ec);
630 return Read<T>(idx, subidx, ec);
634typename ::std::enable_if<is_canopen_basic<T>::value>::type
636 ::std::error_code ec;
642typename ::std::enable_if<is_canopen_basic<T>::value>::type
644 ::std::error_code& ec) {
647 ::std::lock_guard<Impl_> lock(*impl_);
648 ::std::tie(idx, subidx) = impl_->TpdoMapping(
id, idx, subidx, ec);
650 if (!ec)
Write<T>(idx, subidx, value, ec);
653#ifndef DOXYGEN_SHOULD_SKIP_THIS
658 ::std::error_code&)
const;
661 ::std::error_code&)
const;
669 ::std::error_code&)
const;
672 ::std::error_code&)
const;
680 ::std::error_code&)
const;
683 ::std::error_code&)
const;
691 ::std::error_code&)
const;
694 ::std::error_code&)
const;
702 ::std::error_code&)
const;
705 ::std::error_code&)
const;
713 ::std::error_code&)
const;
716 ::std::error_code&)
const;
724 ::std::error_code&)
const;
727 ::std::error_code&)
const;
735 ::std::error_code&)
const;
738 ::std::error_code&)
const;
754 ::std::error_code&)
const;
757 ::std::error_code&)
const;
769 ::std::error_code&)
const;
772 ::std::error_code&)
const;
785 ::std::error_code&)
const;
788 ::std::error_code&)
const;
797 ::std::error_code ec;
804 ::std::error_code& ec)
noexcept {
805 ::std::lock_guard<Impl_> lock(*impl_);
807 TpdoSetEvent(
id, idx, subidx, ec);
812 ::std::lock_guard<Impl_> lock(*impl_);
813 impl_->on_write = on_write;
822 ::std::lock_guard<Impl_> lock(*impl_);
823 impl_->on_rpdo_write = on_rpdo_write;
829 return impl_->dev.get();
832const ::std::type_info&
834 ::std::error_code ec;
835 auto&
ti =
Type(idx, subidx, ec);
840const ::std::type_info&
842 ::std::error_code& ec)
const noexcept {
872 return typeid(
float);
874 return typeid(::std::string);
876 return typeid(::std::vector<uint8_t>);
878 return typeid(::std::basic_string<char16_t>);
882 return typeid(::std::vector<uint8_t>);
903typename ::std::enable_if<is_canopen<T>::value, T>::type
905 ::std::error_code ec;
906 auto value =
Get<T>(idx, subidx, ec);
912typename ::std::enable_if<is_canopen<T>::value, T>::type
914 ::std::error_code& ec)
const noexcept {
916 using c_type =
typename traits::c_type;
938 return traits::from_c_type(*
pval);
942typename ::std::enable_if<is_canopen<T>::value>::type
944 ::std::error_code ec;
945 Set(idx, subidx, value, ec);
950typename ::std::enable_if<is_canopen<T>::value>::type
952 ::std::error_code& ec)
noexcept {
972 auto val = traits::to_c_type(value, ec);
974 auto p = traits::address(val);
975 auto n = traits::size(val);
982 ec = util::make_error_code();
985 traits::destroy(val);
991 ::std::error_code& ec)
noexcept {
992 Set(idx, subidx, value.c_str(), ec);
998 ::std::error_code& ec)
noexcept {
999 Set(idx, subidx, value.data(), value.size(), ec);
1002#ifndef DOXYGEN_SHOULD_SKIP_THIS
1005template bool Device::Get<bool>(uint16_t, uint8_t)
const;
1006template bool Device::Get<bool>(uint16_t, uint8_t,
1007 ::std::error_code&)
const noexcept;
1008template void Device::Set<bool>(uint16_t, uint8_t,
const bool&);
1009template void Device::Set<bool>(uint16_t, uint8_t,
const bool&,
1010 ::std::error_code&)
noexcept;
1013template int8_t Device::Get<int8_t>(uint16_t, uint8_t)
const;
1014template int8_t Device::Get<int8_t>(uint16_t, uint8_t,
1015 ::std::error_code&)
const noexcept;
1016template void Device::Set<int8_t>(uint16_t, uint8_t,
const int8_t&);
1017template void Device::Set<int8_t>(uint16_t, uint8_t,
const int8_t&,
1018 ::std::error_code&)
noexcept;
1021template int16_t Device::Get<int16_t>(uint16_t, uint8_t)
const;
1022template int16_t Device::Get<int16_t>(uint16_t, uint8_t,
1023 ::std::error_code&)
const noexcept;
1024template void Device::Set<int16_t>(uint16_t, uint8_t,
const int16_t&);
1025template void Device::Set<int16_t>(uint16_t, uint8_t,
const int16_t&,
1026 ::std::error_code&)
noexcept;
1029template int32_t Device::Get<int32_t>(uint16_t, uint8_t)
const;
1030template int32_t Device::Get<int32_t>(uint16_t, uint8_t,
1031 ::std::error_code&)
const noexcept;
1032template void Device::Set<int32_t>(uint16_t, uint8_t,
const int32_t&);
1033template void Device::Set<int32_t>(uint16_t, uint8_t,
const int32_t&,
1034 ::std::error_code&)
noexcept;
1037template uint8_t Device::Get<uint8_t>(uint16_t, uint8_t)
const;
1038template uint8_t Device::Get<uint8_t>(uint16_t, uint8_t,
1039 ::std::error_code&)
const noexcept;
1040template void Device::Set<uint8_t>(uint16_t, uint8_t,
const uint8_t&);
1041template void Device::Set<uint8_t>(uint16_t, uint8_t,
const uint8_t&,
1042 ::std::error_code&)
noexcept;
1045template uint16_t Device::Get<uint16_t>(uint16_t, uint8_t)
const;
1046template uint16_t Device::Get<uint16_t>(uint16_t, uint8_t,
1047 ::std::error_code&)
const noexcept;
1048template void Device::Set<uint16_t>(uint16_t, uint8_t,
const uint16_t&);
1049template void Device::Set<uint16_t>(uint16_t, uint8_t,
const uint16_t&,
1050 ::std::error_code&)
noexcept;
1053template uint32_t Device::Get<uint32_t>(uint16_t, uint8_t)
const;
1054template uint32_t Device::Get<uint32_t>(uint16_t, uint8_t,
1055 ::std::error_code&)
const noexcept;
1056template void Device::Set<uint32_t>(uint16_t, uint8_t,
const uint32_t&);
1057template void Device::Set<uint32_t>(uint16_t, uint8_t,
const uint32_t&,
1058 ::std::error_code&)
noexcept;
1061template float Device::Get<float>(uint16_t, uint8_t)
const;
1062template float Device::Get<float>(uint16_t, uint8_t,
1063 ::std::error_code&)
const noexcept;
1064template void Device::Set<float>(uint16_t, uint8_t,
const float&);
1065template void Device::Set<float>(uint16_t, uint8_t,
const float&,
1066 ::std::error_code&)
noexcept;
1069template ::std::string Device::Get<::std::string>(uint16_t, uint8_t)
const;
1070template ::std::string Device::Get<::std::string>(
1071 uint16_t, uint8_t, ::std::error_code&)
const noexcept;
1072template void Device::Set<::std::string>(uint16_t, uint8_t,
1073 const ::std::string&);
1079template ::std::vector<uint8_t> Device::Get<::std::vector<uint8_t>>(
1080 uint16_t, uint8_t)
const;
1081template ::std::vector<uint8_t> Device::Get<::std::vector<uint8_t>>(
1082 uint16_t, uint8_t, ::std::error_code&)
const noexcept;
1083template void Device::Set<::std::vector<uint8_t>>(
1084 uint16_t, uint8_t, const ::std::vector<uint8_t>&);
1092template ::std::basic_string<char16_t>
1093 Device::Get<::std::basic_string<char16_t>>(uint16_t, uint8_t)
const;
1094template ::std::basic_string<char16_t>
1095Device::Get<::std::basic_string<char16_t>>(uint16_t, uint8_t,
1096 ::std::error_code&)
const noexcept;
1097template void Device::Set<::std::basic_string<char16_t>>(
1098 uint16_t, uint8_t, const ::std::basic_string<char16_t>&);
1099template void Device::Set<::std::basic_string<char16_t>>(
1100 uint16_t, uint8_t, const ::std::basic_string<char16_t>&,
1101 ::std::error_code&)
noexcept;
1109template double Device::Get<double>(uint16_t, uint8_t)
const;
1110template double Device::Get<double>(uint16_t, uint8_t,
1111 ::std::error_code&)
const noexcept;
1112template void Device::Set<double>(uint16_t, uint8_t,
const double&);
1113template void Device::Set<double>(uint16_t, uint8_t,
const double&,
1114 ::std::error_code&)
noexcept;
1121template int64_t Device::Get<int64_t>(uint16_t, uint8_t)
const;
1122template int64_t Device::Get<int64_t>(uint16_t, uint8_t,
1123 ::std::error_code&)
const noexcept;
1124template void Device::Set<int64_t>(uint16_t, uint8_t,
const int64_t&);
1125template void Device::Set<int64_t>(uint16_t, uint8_t,
const int64_t&,
1126 ::std::error_code&)
noexcept;
1134template uint64_t Device::Get<uint64_t>(uint16_t, uint8_t)
const;
1135template uint64_t Device::Get<uint64_t>(uint16_t, uint8_t,
1136 ::std::error_code&)
const noexcept;
1137template void Device::Set<uint64_t>(uint16_t, uint8_t,
const uint64_t&);
1138template void Device::Set<uint64_t>(uint16_t, uint8_t,
const uint64_t&,
1139 ::std::error_code&)
noexcept;
1145 ::std::error_code ec;
1146 Set(idx, subidx, value, ec);
1152 ::std::error_code& ec)
noexcept {
1153 Set(idx, subidx, value, ::std::char_traits<char>::length(value), ec);
1158 ::std::error_code ec;
1159 Set(idx, subidx, value, ec);
1165 ::std::error_code& ec)
noexcept {
1185 auto val = traits::to_c_type(value, ec);
1187 auto p = traits::address(val);
1188 auto n = traits::size(val);
1195 ec = util::make_error_code();
1198 traits::destroy(val);
1203 ::std::error_code ec;
1204 Set(idx, subidx, p, n, ec);
1210 ::std::error_code& ec)
noexcept {
1228 ec = util::make_error_code();
1232#if !LELY_NO_CO_OBJ_FILE
1236 ::std::error_code ec;
1238 if (ec)
throw_sdo_error(impl_->id(), idx, subidx, ec,
"GetUploadFile");
1244 ::std::error_code& ec)
const noexcept {
1263 ::std::error_code ec;
1265 if (ec)
throw_sdo_error(impl_->id(), idx, subidx, ec,
"SetUploadFile");
1270 ::std::error_code& ec)
noexcept {
1288 ec = util::make_error_code();
1294 ::std::error_code ec;
1296 if (ec)
throw_sdo_error(impl_->id(), idx, subidx, ec,
"GetDownloadFile");
1302 ::std::error_code& ec)
const noexcept {
1321 ::std::error_code ec;
1323 if (ec)
throw_sdo_error(impl_->id(), idx, subidx, ec,
"SetDownloadFile");
1328 ::std::error_code& ec)
noexcept {
1346 ec = util::make_error_code();
1354 ::std::error_code ec;
1375#if !LELYY_NO_CO_MPDO
1382typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
1384 ::std::error_code ec;
1385 auto value =
RpdoGet<T>(
id, idx, subidx, ec);
1391typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
1393 ::std::error_code& ec)
const noexcept {
1395 ::std::tie(idx, subidx) = impl_->RpdoMapping(
id, idx, subidx, ec);
1397 return Get<T>(idx, subidx, ec);
1401typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
1403 ::std::error_code ec;
1404 auto value =
TpdoGet<T>(
id, idx, subidx, ec);
1410typename ::std::enable_if<is_canopen_basic<T>::value, T>::type
1412 ::std::error_code& ec)
const noexcept {
1414 ::std::tie(idx, subidx) = impl_->TpdoMapping(
id, idx, subidx, ec);
1416 return Get<T>(idx, subidx, ec);
1420typename ::std::enable_if<is_canopen_basic<T>::value>::type
1422 ::std::error_code ec;
1423 TpdoSet(
id, idx, subidx, value, ec);
1428typename ::std::enable_if<is_canopen_basic<T>::value>::type
1430 ::std::error_code& ec)
noexcept {
1432 ::std::tie(idx, subidx) = impl_->TpdoMapping(
id, idx, subidx, ec);
1433 if (!ec)
Set<T>(idx, subidx, value, ec);
1436#ifndef DOXYGEN_SHOULD_SKIP_THIS
1441 ::std::error_code&)
const noexcept;
1444 ::std::error_code&)
const noexcept;
1447 ::std::error_code&)
noexcept;
1452 ::std::error_code&)
const noexcept;
1455 ::std::error_code&)
const noexcept;
1458 ::std::error_code&)
noexcept;
1463 ::std::error_code&)
const noexcept;
1466 ::std::error_code&)
const noexcept;
1469 ::std::error_code&)
noexcept;
1474 ::std::error_code&)
const noexcept;
1477 ::std::error_code&)
const noexcept;
1480 ::std::error_code&)
noexcept;
1485 ::std::error_code&)
const noexcept;
1488 ::std::error_code&)
const noexcept;
1491 ::std::error_code&)
noexcept;
1496 ::std::error_code&)
const noexcept;
1499 ::std::error_code&)
const noexcept;
1502 ::std::error_code&)
noexcept;
1507 ::std::error_code&)
const noexcept;
1510 ::std::error_code&)
const noexcept;
1513 ::std::error_code&)
noexcept;
1518 ::std::error_code&)
const noexcept;
1521 ::std::error_code&)
const noexcept;
1524 ::std::error_code&)
noexcept;
1537 ::std::error_code&)
const noexcept;
1540 ::std::error_code&)
const noexcept;
1543 ::std::error_code&)
noexcept;
1552 ::std::error_code&)
const noexcept;
1555 ::std::error_code&)
const noexcept;
1558 ::std::error_code&)
noexcept;
1568 ::std::error_code&)
const noexcept;
1571 ::std::error_code&)
const noexcept;
1574 ::std::error_code&)
noexcept;
1580 ::std::error_code ec;
1587 ::std::error_code& ec)
noexcept {
1589 ::std::tie(idx, subidx) = impl_->TpdoMapping(
id, idx, subidx, ec);
1590 if (!ec) SetEvent(idx, subidx, ec);
1596 impl_->rpdo_mapping.clear();
1604 if (
i >= 512)
break;
1616 switch (cobid & 0x780) {
1639 for (
int j = 1;
j <= n;
j++) {
1645 if ((
rmap & 0xff) != (
tmap & 0xff))
break;
1696 uint8_t min = (val >> 8) & 0xff;
1699 if (
blk) max += ::std::min(
blk - 1, 0xff - min);
1701 for (
int j = 0;
j <= max - min;
j++) {
1703 if (
static_cast<uint8_t>(
j) > 0xff - (
rmap & 0xff))
break;
1716 impl_->tpdo_mapping.clear();
1724 if (
i >= 512)
break;
1736 switch (cobid & 0x780) {
1759 for (
int j = 1;
j <= n;
j++) {
1765 if ((
tmap & 0xff) != (
rmap & 0xff))
break;
1782 OnRpdoWrite(
id, idx, subidx);
1784 if (impl_->on_rpdo_write) {
1785 auto f = impl_->on_rpdo_write;
1793Device::Impl_::Impl_(
Device* self_, const ::std::string&
dcf_txt,
1801 util::throw_errc(
"Device");
1804 util::throw_errc(
"Device");
1820 auto impl_ =
static_cast<Impl_*
>(data);
1825 static_cast<void*
>(
this));
1831Device::Impl_::OnWrite(uint16_t idx, uint8_t subidx) {
1832 self->OnWrite(idx, subidx);
1836 util::UnlockGuard<Impl_>
unlock(*
this);
1842 ::std::error_code ec;
1843 ::std::tie(
id, idx, subidx) = RpdoMapping(idx, subidx, ec);
1844 if (!ec) self->
RpdoWrite(
id, idx, subidx);
This header file is part of the utilities library; it contains the bit function definitions.
uint_least32_t ror32(uint_least32_t x, unsigned int n)
Rotates the 32-bit unsigned integer x right by n bits.
The CANopen device description.
void RpdoWrite(uint8_t id, uint16_t idx, uint8_t subidx)
Invokes OnRpdoWrite() as if a value was written to an RPDO-mapped object in the local object dictiona...
uint8_t netid() const noexcept
Returns the network-ID.
void SetUploadFile(uint16_t idx, uint8_t subidx, const char *filename)
Sets the value of the UploadFile attribute of a sub-object, if present.
typename::std::enable_if< is_canopen_basic< T >::value, T >::type RpdoGet(uint8_t id, uint16_t idx, uint8_t subidx) const
Reads the value of a sub-object in a remote object dictionary by reading the corresponding PDO-mapped...
void TpdoWriteEvent(uint8_t id, uint16_t idx, uint8_t subidx)
Triggers the transmission of every event-driven, asynchronous Transmit-PDO which is mapped into the s...
void WriteDcf(const uint8_t *begin, const uint8_t *end)
Submits a series of SDO download requests to the local object dictionary.
void UpdateTpdoMapping()
Updates the mapping from remote RPDO-mapped sub-objects to local TPDO-mapped sub-objects.
typename::std::enable_if< is_canopen_basic< T >::value, T >::type TpdoGet(uint8_t id, uint16_t idx, uint8_t subidx) const
Reads the value of a TPDO-mapped sub-object in the local object dictionary that will be written to an...
typename::std::enable_if< is_canopen< T >::value, T >::type Read(uint16_t idx, uint8_t subidx) const
Submits an SDO upload request to the local object dictionary.
void SetDownloadFile(uint16_t idx, uint8_t subidx, const char *filename)
Sets the value of the DownloadFile attribute of a sub-object, if present.
typename::std::enable_if< is_canopen_basic< T >::value >::type TpdoWrite(uint8_t id, uint16_t idx, uint8_t subidx, T value)
Writes a value to a sub-object in a remote object dictionary by submitting an SDO download request to...
const ::std::type_info & Type(uint16_t idx, uint8_t subidx) const
Returns the type of a sub-object.
typename::std::enable_if< is_canopen< T >::value >::type Set(uint16_t idx, uint8_t subidx, const T &value)
Writes a CANopen value to a sub-object.
void UpdateRpdoMapping()
Updates the mapping from remote TPDO-mapped sub-objects to local RPDO-mapped sub-objects.
typename::std::enable_if< is_canopen< T >::value, T >::type Get(uint16_t idx, uint8_t subidx) const
Reads the value of a sub-object.
void SetEvent(uint16_t idx, uint8_t subidx)
Checks if the specified sub-object in the local object dictionary can be mapped into a PDO and,...
void WriteEvent(uint16_t idx, uint8_t subidx)
Checks if the specified sub-object in the local object dictionary can be mapped into a PDO and,...
typename::std::enable_if< is_canopen_basic< T >::value >::type TpdoSet(uint8_t id, uint16_t idx, uint8_t subidx, T value)
Writes a value to a sub-object in a remote object dictionary by writing to the corresponding PDO-mapp...
Device(const ::std::string &dcf_txt, const ::std::string &dcf_bin="", uint8_t id=0xff, util::BasicLockable *mutex=nullptr)
Creates a new CANopen device description.
typename::std::enable_if< is_canopen< T >::value >::type Write(uint16_t idx, uint8_t subidx, const T &value)
Submits an SDO download request to the local object dictionary.
const char * GetDownloadFile(uint16_t idx, uint8_t subidx) const
Returns the value of the DownloadFile attribute of a sub-object, if present.
typename::std::enable_if< is_canopen_basic< T >::value, T >::type TpdoRead(uint8_t id, uint16_t idx, uint8_t subidx) const
Submits an SDO upload request to a TPDO-mapped sub-object in the local object dictionary,...
typename::std::enable_if< is_canopen_basic< T >::value, T >::type RpdoRead(uint8_t id, uint16_t idx, uint8_t subidx) const
Reads the value of a sub-object in a remote object dictionary by submitting an SDO upload request to ...
void TpdoSetEvent(uint8_t id, uint16_t idx, uint8_t subidx)
Triggers the transmission of every event-driven, asynchronous Transmit-PDO which is mapped into the s...
__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.
const char * GetUploadFile(uint16_t idx, uint8_t subidx) const
Returns the value of the UploadFile attribute of a sub-object, if present.
An abstract interface conforming to the BasicLockable concept.
A mutex wrapper that provides a convenient RAII-style mechanism for releasing a mutex for the duratio...
This header file is part of the CANopen library; it contains the device description declarations.
void co_dev_sam_mpdo_event(co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Checks if the specified sub-object in the object dictionary of a CANopen device can be mapped into a ...
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.
int co_dev_set_id(co_dev_t *dev, co_unsigned8_t id)
Sets the node-ID of a CANopen device.
#define CO_NUM_NODES
The maximum number of nodes in a CANopen network.
co_unsigned8_t co_dev_get_netid(const co_dev_t *dev)
Returns the network-ID of a CANopen device.
void co_dev_destroy(co_dev_t *dev)
Destroys a CANopen device, including all objects in its object dictionary.
void co_dev_tpdo_event(co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Checks if the specified sub-object in the object dictionary of a CANopen device can be mapped into a ...
co_obj_t * co_dev_first_obj(const co_dev_t *dev)
Finds the first object (with the lowest index) in the object dictionary of a CANopen device.
int co_dev_read_dcf_file(co_dev_t *dev, co_unsigned16_t *pmin, co_unsigned16_t *pmax, const char *filename)
Reads the values of a range of objects from a file, in the concise DCF format, and stores them in the...
This is the internal header file of the C++ CANopen application library.
This header file is part of the CANopen library; it contains the Client-SDO declarations.
int co_dev_up_req(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx, co_csdo_up_con_t *con, void *data)
Submits an upload request to a local device.
int co_dev_dn_val_req(co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx, co_unsigned16_t type, const void *val, co_csdo_dn_con_t *con, void *data)
Submits a download request to a local device.
int co_dev_dn_req(co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx, const void *ptr, size_t n, co_csdo_dn_con_t *con, void *data)
Submits a download request to a local device.
int co_dev_dn_dcf_req(co_dev_t *dev, const uint_least8_t *begin, const uint_least8_t *end, co_csdo_dn_con_t *con, void *data)
Submits a series of download requests to a local device.
This header file is part of the CANopen library; it contains the Electronic Data Sheet (EDS) and Devi...
co_dev_t * co_dev_create_from_dcf_file(const char *filename)
Creates a CANopen device from an EDS or DCF file.
This header file is part of the C++ CANopen application library; it contains the CANopen device descr...
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
This header file is part of the utilities library; it contains C++ convenience functions for creating...
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.
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.
@ NO_PDO
Object cannot be mapped to the PDO.
SdoErrc sdo_errc(::std::error_code ec)
Returns the SDO abort code corresponding to an error code.
void throw_sdo_error(uint8_t id, uint16_t idx, uint8_t subidx, ::std::error_code ec)
Throws a lely::canopen::SdoError with the specified attributes if ec is an SDO error (ec....
This header file is part of the CANopen library; it contains the object dictionary declarations.
co_sub_t * co_obj_first_sub(const co_obj_t *obj)
Finds the first sub-object (with the lowest sub-index) in a CANopen object.
co_unsigned8_t co_sub_get_subidx(const co_sub_t *sub)
Returns the sub-index of a CANopen sub-object.
int co_sub_set_download_file(co_sub_t *sub, const char *filename)
Sets the value of the DownloadFile attribute of 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.
const char * co_sub_get_download_file(const co_sub_t *sub)
Returns a pointer to the value of the DownloadFile attribute of a CANopen sub-object,...
int co_sub_set_upload_file(co_sub_t *sub, const char *filename)
Sets the value of the UploadFile attribute of 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.
size_t co_sub_set_val(co_sub_t *sub, const void *ptr, size_t n)
Sets the current value of a CANopen sub-object.
const char * co_sub_get_upload_file(const co_sub_t *sub)
Returns a pointer to the value of the UploadFile attribute of a CANopen sub-object,...
co_obj_t * co_obj_next(const co_obj_t *obj)
Finds the next object in the object dictionary of a CANopen device.
int co_sub_on_dn(co_sub_t *sub, struct co_sdo_req *req, co_unsigned32_t *pac)
Implements the default behavior when a download indication is received by a CANopen sub-object.
void co_obj_set_dn_ind(co_obj_t *obj, co_sub_dn_ind_t *ind, void *data)
Sets the download indication function for a CANopen object.
co_sub_t * co_sub_next(const co_sub_t *sub)
Finds the next sub-object in a CANopen object.
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_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 CANopen library; it contains the Process Data Object (PDO) declaratio...
#define CO_PDO_NUM_MAPS
The maximum number of mapped application objects in a single PDO.
#define CO_PDO_COBID_FRAME
The bit in the PDO COB-ID specifying whether to use an 11-bit (0) or 29-bit (1) CAN-ID.
#define CO_PDO_COBID_VALID
The bit in the PDO COB-ID specifying whether the PDO exists and is valid.
#define CO_NUM_PDOS
The maximum number of Receive/Transmit-PDOs.
#define CO_PDO_MAP_SAM_MPDO
The value of sub-index 0 of the PDO mapping parameter record indicating a a source address mode multi...
A CANopen SDO upload/download request.
The internal implementation of the CANopen device description.
void lock() override
Blocks until a lock can be obtained for the current execution agent (thread, process,...
void unlock() override
Releases the lock held by the execution agent. Throws no exceptions.
#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.
int co_type_is_basic(co_unsigned16_t type)
Returns 1 if the specified (static) data type is a basic type, and 0 if not.
#define CO_DEFTYPE_REAL32
The data type (and object index) of a 32-bit IEEE-754 floating-point number.
This header file is part of the CANopen library; it contains the CANopen value declarations.
const void * co_val_addressof(co_unsigned16_t type, const void *val)
Returns the address of the first byte in a value of the specified data type.
size_t co_val_sizeof(co_unsigned16_t type, const void *val)
Returns the size (in bytes) of a value of the specified data type.
size_t co_val_read_file(co_unsigned16_t type, void *val, const char *filename)
Reads a value of the specified data type from a file.
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.