Lely core libraries  2.2.5
slave.cpp
Go to the documentation of this file.
1 
24 #include "coapp.hpp"
25 
26 #if !LELY_NO_COAPP_SLAVE
27 
28 #include <lely/coapp/slave.hpp>
29 
30 #include <map>
31 #include <string>
32 #include <utility>
33 #include <vector>
34 
35 #include <cassert>
36 
37 #include <lely/co/dev.hpp>
38 #include <lely/co/nmt.hpp>
39 #include <lely/co/obj.hpp>
40 
41 namespace lely {
42 
43 namespace canopen {
44 
47  Impl_(BasicSlave* self, CONMT* nmt);
48 
49  uint8_t
50  netid() const noexcept {
51  return self->dev()->getNetid();
52  }
53 
54  uint8_t
55  id() const noexcept {
56  return self->dev()->getId();
57  }
58 
59  void OnLgInd(CONMT* nmt, int state) noexcept;
60 
61  template <uint16_t N>
62  uint32_t OnDnInd(COSub* sub, COVal<N>& val) noexcept;
63 
64  template <uint16_t N>
65  uint32_t OnUpInd(const COSub* sub, COVal<N>& val) noexcept;
66 
67  static constexpr uint32_t Key(uint16_t idx, uint8_t subidx) noexcept;
68  static uint32_t Key(const COSub* sub) noexcept;
69 
70  BasicSlave* self;
71 
72  ::std::map<uint32_t, ::std::function<uint32_t(COSub*, void*)>> dn_ind;
73  ::std::map<uint32_t, ::std::function<uint32_t(const COSub*, void*)>> up_ind;
74 
75  ::std::function<void(bool)> on_life_guarding;
76 };
77 
79  io::CanChannelBase& chan, const ::std::string& dcf_txt,
80  const ::std::string& dcf_bin, uint8_t id)
81  : Node(exec, timer, chan, dcf_txt, dcf_bin, id),
82  impl_(new Impl_(this, Node::nmt())) {}
83 
84 BasicSlave::~BasicSlave() = default;
85 
86 void
87 BasicSlave::OnLifeGuarding(::std::function<void(bool)> on_life_guarding) {
88  ::std::lock_guard<util::BasicLockable> lock(*this);
89  impl_->on_life_guarding = on_life_guarding;
90 }
91 
92 template <class T>
93 typename ::std::enable_if<detail::is_canopen_type<T>::value>::type
94 BasicSlave::OnRead(uint16_t idx, uint8_t subidx,
95  ::std::function<OnReadSignature<T>> ind) {
96  ::std::error_code ec;
97  OnRead<T>(idx, subidx, ::std::move(ind), ec);
98  if (ec) throw SdoError(impl_->id(), idx, subidx, ec);
99 }
100 
101 namespace {
102 
103 template <class T, class F, uint16_t N = co_type_traits_T<T>::index>
104 typename ::std::enable_if<detail::is_canopen_basic<T>::value,
105  ::std::error_code>::type
106 OnUpInd(const COSub* sub, COVal<N>& val, const F& ind) {
107  assert(sub);
108 
109  try {
110  return ind(sub->getObj()->getIdx(), sub->getSubidx(), val);
111  } catch (...) {
112  return SdoErrc::ERROR;
113  }
114 }
115 
116 template <class T, class F, uint16_t N = co_type_traits_T<T>::index>
117 typename ::std::enable_if<detail::is_canopen_array<T>::value,
118  ::std::error_code>::type
119 OnUpInd(const COSub* sub, COVal<N>& val, const F& ind) {
120  assert(sub);
121 
122  try {
123  T value = val;
124  auto ec = ind(sub->getObj()->getIdx(), sub->getSubidx(), value);
125  if (!ec) val = ::std::move(value);
126  return ec;
127  } catch (...) {
128  return SdoErrc::ERROR;
129  }
130 }
131 
132 } // namespace
133 
134 template <class T>
135 typename ::std::enable_if<detail::is_canopen_type<T>::value>::type
136 BasicSlave::OnRead(uint16_t idx, uint8_t subidx,
137  ::std::function<OnReadSignature<T>> ind,
138  ::std::error_code& ec) {
139  constexpr auto N = co_type_traits_T<T>::index;
140 
141  auto obj = dev()->find(idx);
142  if (!obj) {
143  ec = SdoErrc::NO_OBJ;
144  return;
145  }
146 
147  auto sub = obj->find(subidx);
148  if (!sub) {
149  ec = SdoErrc::NO_SUB;
150  return;
151  }
152 
153  if (!detail::is_canopen_same(N, sub->getType())) {
154  ec = SdoErrc::TYPE_LEN;
155  return;
156  }
157 
158  auto key = Impl_::Key(sub);
159  if (ind) {
160  impl_->up_ind[key] = [this, ind](const COSub* sub, void* p) {
161  auto ec = OnUpInd<T>(sub, *static_cast<COVal<N>*>(p), ind);
162  return static_cast<uint32_t>(ec.value());
163  };
164  sub->setUpInd<N, Impl_, &Impl_::OnUpInd>(impl_.get());
165  } else {
166  if (impl_->up_ind.erase(key)) sub->setUpInd(nullptr, nullptr);
167  }
168 }
169 
170 template <class T>
171 typename ::std::enable_if<detail::is_canopen_type<T>::value>::type
172 BasicSlave::OnRead(uint16_t idx, ::std::function<OnReadSignature<T>> ind) {
173  uint8_t n = (*this)[idx][0];
174  for (uint8_t i = 1; i <= n; i++) OnRead<T>(idx, i, ind);
175 }
176 
177 template <class T>
178 typename ::std::enable_if<detail::is_canopen_type<T>::value>::type
179 BasicSlave::OnRead(uint16_t idx, ::std::function<OnReadSignature<T>> ind,
180  ::std::error_code& ec) {
181  uint8_t n = (*this)[idx][0].Get<uint8_t>(ec);
182  for (uint8_t i = 1; i <= n && !ec; i++) OnRead<T>(idx, i, ind, ec);
183 }
184 
185 template <class T>
186 typename ::std::enable_if<detail::is_canopen_type<T>::value>::type
187 BasicSlave::OnWrite(uint16_t idx, uint8_t subidx,
188  ::std::function<OnWriteSignature<T>> ind) {
189  ::std::error_code ec;
190  OnWrite<T>(idx, subidx, ::std::move(ind), ec);
191  if (ec) throw SdoError(impl_->id(), idx, subidx, ec);
192 }
193 
194 namespace {
195 
196 template <class T, class F, uint16_t N = co_type_traits_T<T>::index>
197 typename ::std::enable_if<detail::is_canopen_basic<T>::value,
198  ::std::error_code>::type
199 OnDnInd(COSub* sub, COVal<N>& val, const F& ind) {
200  assert(sub);
201 
202  try {
203  return ind(sub->getObj()->getIdx(), sub->getSubidx(), val,
204  sub->getVal<N>());
205  } catch (...) {
206  return SdoErrc::ERROR;
207  }
208 }
209 
210 template <class T, class F, uint16_t N = co_type_traits_T<T>::index>
211 typename ::std::enable_if<detail::is_canopen_array<T>::value,
212  ::std::error_code>::type
213 OnDnInd(COSub* sub, COVal<N>& val, const F& ind) {
214  assert(sub);
215 
216  try {
217  T value = val;
218  auto ec = ind(sub->getObj()->getIdx(), sub->getSubidx(), value);
219  if (!ec) val = ::std::move(value);
220  return ec;
221  } catch (...) {
222  return SdoErrc::ERROR;
223  }
224 }
225 
226 } // namespace
227 
228 template <class T>
229 typename ::std::enable_if<detail::is_canopen_type<T>::value>::type
230 BasicSlave::OnWrite(uint16_t idx, uint8_t subidx,
231  ::std::function<OnWriteSignature<T>> ind,
232  ::std::error_code& ec) {
233  constexpr auto N = co_type_traits_T<T>::index;
234 
235  auto obj = dev()->find(idx);
236  if (!obj) {
237  ec = SdoErrc::NO_OBJ;
238  return;
239  }
240 
241  auto sub = obj->find(subidx);
242  if (!sub) {
243  ec = SdoErrc::NO_SUB;
244  return;
245  }
246 
247  if (!detail::is_canopen_same(N, sub->getType())) {
248  ec = SdoErrc::TYPE_LEN;
249  return;
250  }
251 
252  auto key = Impl_::Key(sub);
253  if (ind) {
254  impl_->dn_ind[key] = [this, ind](COSub* sub, void* p) {
255  auto ec = OnDnInd<T>(sub, *static_cast<COVal<N>*>(p), ind);
256  return static_cast<uint32_t>(ec.value());
257  };
258  sub->setDnInd<N, Impl_, &Impl_::OnDnInd>(impl_.get());
259  } else {
260  if (impl_->dn_ind.erase(key)) sub->setDnInd(nullptr, nullptr);
261  }
262 }
263 
264 template <class T>
265 typename ::std::enable_if<detail::is_canopen_type<T>::value>::type
266 BasicSlave::OnWrite(uint16_t idx, ::std::function<OnWriteSignature<T>> ind) {
267  uint8_t n = (*this)[idx][0];
268  for (uint8_t i = 1; i <= n; i++) OnWrite<T>(idx, i, ind);
269 }
270 
271 template <class T>
272 typename ::std::enable_if<detail::is_canopen_type<T>::value>::type
273 BasicSlave::OnWrite(uint16_t idx, ::std::function<OnWriteSignature<T>> ind,
274  ::std::error_code& ec) {
275  uint8_t n = (*this)[idx][0].Get<uint8_t>(ec);
276  for (uint8_t i = 1; i <= n && !ec; i++) OnWrite<T>(idx, i, ind, ec);
277 }
278 
279 #ifndef DOXYGEN_SHOULD_SKIP_THIS
280 
281 // BOOLEAN
282 template void BasicSlave::OnRead<bool>(uint16_t, uint8_t,
283  ::std::function<OnReadSignature<bool>>);
284 template void BasicSlave::OnRead<bool>(uint16_t, uint8_t,
285  ::std::function<OnReadSignature<bool>>,
286  ::std::error_code&);
287 template void BasicSlave::OnRead<bool>(uint16_t,
288  ::std::function<OnReadSignature<bool>>);
289 template void BasicSlave::OnRead<bool>(uint16_t,
290  ::std::function<OnReadSignature<bool>>,
291  ::std::error_code&);
292 template void BasicSlave::OnWrite<bool>(
293  uint16_t, uint8_t, ::std::function<OnWriteSignature<bool>>);
294 template void BasicSlave::OnWrite<bool>(uint16_t, uint8_t,
295  ::std::function<OnWriteSignature<bool>>,
296  ::std::error_code&);
297 template void BasicSlave::OnWrite<bool>(
298  uint16_t, ::std::function<OnWriteSignature<bool>>);
299 template void BasicSlave::OnWrite<bool>(uint16_t,
300  ::std::function<OnWriteSignature<bool>>,
301  ::std::error_code&);
302 
303 // INTEGER8
304 template void BasicSlave::OnRead<int8_t>(
305  uint16_t, uint8_t, ::std::function<OnReadSignature<int8_t>>);
306 template void BasicSlave::OnRead<int8_t>(
307  uint16_t, uint8_t, ::std::function<OnReadSignature<int8_t>>,
308  ::std::error_code&);
309 template void BasicSlave::OnRead<int8_t>(
310  uint16_t, ::std::function<OnReadSignature<int8_t>>);
311 template void BasicSlave::OnRead<int8_t>(
312  uint16_t, ::std::function<OnReadSignature<int8_t>>, ::std::error_code&);
313 template void BasicSlave::OnWrite<int8_t>(
314  uint16_t, uint8_t, ::std::function<OnWriteSignature<int8_t>>);
315 template void BasicSlave::OnWrite<int8_t>(
316  uint16_t, uint8_t, ::std::function<OnWriteSignature<int8_t>>,
317  ::std::error_code&);
318 template void BasicSlave::OnWrite<int8_t>(
319  uint16_t, ::std::function<OnWriteSignature<int8_t>>);
320 template void BasicSlave::OnWrite<int8_t>(
321  uint16_t, ::std::function<OnWriteSignature<int8_t>>, ::std::error_code&);
322 
323 // INTEGER16
324 template void BasicSlave::OnRead<int16_t>(
325  uint16_t, uint8_t, ::std::function<OnReadSignature<int16_t>>);
326 template void BasicSlave::OnRead<int16_t>(
327  uint16_t, uint8_t, ::std::function<OnReadSignature<int16_t>>,
328  ::std::error_code&);
329 template void BasicSlave::OnRead<int16_t>(
330  uint16_t, ::std::function<OnReadSignature<int16_t>>);
331 template void BasicSlave::OnRead<int16_t>(
332  uint16_t, ::std::function<OnReadSignature<int16_t>>, ::std::error_code&);
333 template void BasicSlave::OnWrite<int16_t>(
334  uint16_t, uint8_t, ::std::function<OnWriteSignature<int16_t>>);
335 template void BasicSlave::OnWrite<int16_t>(
336  uint16_t, uint8_t, ::std::function<OnWriteSignature<int16_t>>,
337  ::std::error_code&);
338 template void BasicSlave::OnWrite<int16_t>(
339  uint16_t, ::std::function<OnWriteSignature<int16_t>>);
340 template void BasicSlave::OnWrite<int16_t>(
341  uint16_t, ::std::function<OnWriteSignature<int16_t>>, ::std::error_code&);
342 
343 // INTEGER32
344 template void BasicSlave::OnRead<int32_t>(
345  uint16_t, uint8_t, ::std::function<OnReadSignature<int32_t>>);
346 template void BasicSlave::OnRead<int32_t>(
347  uint16_t, uint8_t, ::std::function<OnReadSignature<int32_t>>,
348  ::std::error_code&);
349 template void BasicSlave::OnRead<int32_t>(
350  uint16_t, ::std::function<OnReadSignature<int32_t>>);
351 template void BasicSlave::OnRead<int32_t>(
352  uint16_t, ::std::function<OnReadSignature<int32_t>>, ::std::error_code&);
353 template void BasicSlave::OnWrite<int32_t>(
354  uint16_t, uint8_t, ::std::function<OnWriteSignature<int32_t>>);
355 template void BasicSlave::OnWrite<int32_t>(
356  uint16_t, uint8_t, ::std::function<OnWriteSignature<int32_t>>,
357  ::std::error_code&);
358 template void BasicSlave::OnWrite<int32_t>(
359  uint16_t, ::std::function<OnWriteSignature<int32_t>>);
360 template void BasicSlave::OnWrite<int32_t>(
361  uint16_t, ::std::function<OnWriteSignature<int32_t>>, ::std::error_code&);
362 
363 // UNSIGNED8
364 template void BasicSlave::OnRead<uint8_t>(
365  uint16_t, uint8_t, ::std::function<OnReadSignature<uint8_t>>);
366 template void BasicSlave::OnRead<uint8_t>(
367  uint16_t, uint8_t, ::std::function<OnReadSignature<uint8_t>>,
368  ::std::error_code&);
369 template void BasicSlave::OnRead<uint8_t>(
370  uint16_t, ::std::function<OnReadSignature<uint8_t>>);
371 template void BasicSlave::OnRead<uint8_t>(
372  uint16_t, ::std::function<OnReadSignature<uint8_t>>, ::std::error_code&);
373 template void BasicSlave::OnWrite<uint8_t>(
374  uint16_t, uint8_t, ::std::function<OnWriteSignature<uint8_t>>);
375 template void BasicSlave::OnWrite<uint8_t>(
376  uint16_t, uint8_t, ::std::function<OnWriteSignature<uint8_t>>,
377  ::std::error_code&);
378 template void BasicSlave::OnWrite<uint8_t>(
379  uint16_t, ::std::function<OnWriteSignature<uint8_t>>);
380 template void BasicSlave::OnWrite<uint8_t>(
381  uint16_t, ::std::function<OnWriteSignature<uint8_t>>, ::std::error_code&);
382 
383 // UNSIGNED16
384 template void BasicSlave::OnRead<uint16_t>(
385  uint16_t, uint8_t, ::std::function<OnReadSignature<uint16_t>>);
386 template void BasicSlave::OnRead<uint16_t>(
387  uint16_t, uint8_t, ::std::function<OnReadSignature<uint16_t>>,
388  ::std::error_code&);
389 template void BasicSlave::OnRead<uint16_t>(
390  uint16_t, ::std::function<OnReadSignature<uint16_t>>);
391 template void BasicSlave::OnRead<uint16_t>(
392  uint16_t, ::std::function<OnReadSignature<uint16_t>>, ::std::error_code&);
393 template void BasicSlave::OnWrite<uint16_t>(
394  uint16_t, uint8_t, ::std::function<OnWriteSignature<uint16_t>>);
395 template void BasicSlave::OnWrite<uint16_t>(
396  uint16_t, uint8_t, ::std::function<OnWriteSignature<uint16_t>>,
397  ::std::error_code&);
398 template void BasicSlave::OnWrite<uint16_t>(
399  uint16_t, ::std::function<OnWriteSignature<uint16_t>>);
400 template void BasicSlave::OnWrite<uint16_t>(
401  uint16_t, ::std::function<OnWriteSignature<uint16_t>>, ::std::error_code&);
402 
403 // UNSIGNED32
404 template void BasicSlave::OnRead<uint32_t>(
405  uint16_t, uint8_t, ::std::function<OnReadSignature<uint32_t>>);
406 template void BasicSlave::OnRead<uint32_t>(
407  uint16_t, uint8_t, ::std::function<OnReadSignature<uint32_t>>,
408  ::std::error_code&);
409 template void BasicSlave::OnRead<uint32_t>(
410  uint16_t, ::std::function<OnReadSignature<uint32_t>>);
411 template void BasicSlave::OnRead<uint32_t>(
412  uint16_t, ::std::function<OnReadSignature<uint32_t>>, ::std::error_code&);
413 template void BasicSlave::OnWrite<uint32_t>(
414  uint16_t, uint8_t, ::std::function<OnWriteSignature<uint32_t>>);
415 template void BasicSlave::OnWrite<uint32_t>(
416  uint16_t, uint8_t, ::std::function<OnWriteSignature<uint32_t>>,
417  ::std::error_code&);
418 template void BasicSlave::OnWrite<uint32_t>(
419  uint16_t, ::std::function<OnWriteSignature<uint32_t>>);
420 template void BasicSlave::OnWrite<uint32_t>(
421  uint16_t, ::std::function<OnWriteSignature<uint32_t>>, ::std::error_code&);
422 
423 // REAL32
424 template void BasicSlave::OnRead<float>(
425  uint16_t, uint8_t, ::std::function<OnReadSignature<float>>);
426 template void BasicSlave::OnRead<float>(uint16_t, uint8_t,
427  ::std::function<OnReadSignature<float>>,
428  ::std::error_code&);
429 template void BasicSlave::OnRead<float>(
430  uint16_t, ::std::function<OnReadSignature<float>>);
431 template void BasicSlave::OnRead<float>(uint16_t,
432  ::std::function<OnReadSignature<float>>,
433  ::std::error_code&);
434 template void BasicSlave::OnWrite<float>(
435  uint16_t, uint8_t, ::std::function<OnWriteSignature<float>>);
436 template void BasicSlave::OnWrite<float>(
437  uint16_t, uint8_t, ::std::function<OnWriteSignature<float>>,
438  ::std::error_code&);
439 template void BasicSlave::OnWrite<float>(
440  uint16_t, ::std::function<OnWriteSignature<float>>);
441 template void BasicSlave::OnWrite<float>(
442  uint16_t, ::std::function<OnWriteSignature<float>>, ::std::error_code&);
443 
444 // VISIBLE_STRING
445 template void BasicSlave::OnRead<::std::string>(
446  uint16_t, uint8_t, ::std::function<OnReadSignature<::std::string>>);
447 template void BasicSlave::OnRead<::std::string>(
448  uint16_t, uint8_t, ::std::function<OnReadSignature<::std::string>>,
449  ::std::error_code&);
450 template void BasicSlave::OnRead<::std::string>(
451  uint16_t, ::std::function<OnReadSignature<::std::string>>);
452 template void BasicSlave::OnRead<::std::string>(
453  uint16_t, ::std::function<OnReadSignature<::std::string>>,
454  ::std::error_code&);
455 template void BasicSlave::OnWrite<::std::string>(
456  uint16_t, uint8_t, ::std::function<OnWriteSignature<::std::string>>);
457 template void BasicSlave::OnWrite<::std::string>(
458  uint16_t, uint8_t, ::std::function<OnWriteSignature<::std::string>>,
459  ::std::error_code&);
460 template void BasicSlave::OnWrite<::std::string>(
461  uint16_t, ::std::function<OnWriteSignature<::std::string>>);
462 template void BasicSlave::OnWrite<::std::string>(
463  uint16_t, ::std::function<OnWriteSignature<::std::string>>,
464  ::std::error_code&);
465 
466 // OCTET_STRING
467 template void BasicSlave::OnRead<::std::vector<uint8_t>>(
468  uint16_t, uint8_t,
469  ::std::function<OnReadSignature<::std::vector<uint8_t>>>);
470 template void BasicSlave::OnRead<::std::vector<uint8_t>>(
471  uint16_t, uint8_t, ::std::function<OnReadSignature<::std::vector<uint8_t>>>,
472  ::std::error_code&);
473 template void BasicSlave::OnRead<::std::vector<uint8_t>>(
474  uint16_t, ::std::function<OnReadSignature<::std::vector<uint8_t>>>);
475 template void BasicSlave::OnRead<::std::vector<uint8_t>>(
476  uint16_t, ::std::function<OnReadSignature<::std::vector<uint8_t>>>,
477  ::std::error_code&);
478 template void BasicSlave::OnWrite<::std::vector<uint8_t>>(
479  uint16_t, uint8_t,
480  ::std::function<OnWriteSignature<::std::vector<uint8_t>>>);
481 template void BasicSlave::OnWrite<::std::vector<uint8_t>>(
482  uint16_t, uint8_t,
483  ::std::function<OnWriteSignature<::std::vector<uint8_t>>>,
484  ::std::error_code&);
485 template void BasicSlave::OnWrite<::std::vector<uint8_t>>(
486  uint16_t, ::std::function<OnWriteSignature<::std::vector<uint8_t>>>);
487 template void BasicSlave::OnWrite<::std::vector<uint8_t>>(
488  uint16_t, ::std::function<OnWriteSignature<::std::vector<uint8_t>>>,
489  ::std::error_code&);
490 
491 // UNICODE_STRING
492 template void BasicSlave::OnRead<::std::basic_string<char16_t>>(
493  uint16_t, uint8_t,
494  ::std::function<OnReadSignature<::std::basic_string<char16_t>>>);
495 template void BasicSlave::OnRead<::std::basic_string<char16_t>>(
496  uint16_t, uint8_t,
497  ::std::function<OnReadSignature<::std::basic_string<char16_t>>>,
498  ::std::error_code&);
499 template void BasicSlave::OnRead<::std::basic_string<char16_t>>(
500  uint16_t, ::std::function<OnReadSignature<::std::basic_string<char16_t>>>);
501 template void BasicSlave::OnRead<::std::basic_string<char16_t>>(
502  uint16_t, ::std::function<OnReadSignature<::std::basic_string<char16_t>>>,
503  ::std::error_code&);
504 template void BasicSlave::OnWrite<::std::basic_string<char16_t>>(
505  uint16_t, uint8_t,
506  ::std::function<OnWriteSignature<::std::basic_string<char16_t>>>);
507 template void BasicSlave::OnWrite<::std::basic_string<char16_t>>(
508  uint16_t, uint8_t,
509  ::std::function<OnWriteSignature<::std::basic_string<char16_t>>>,
510  ::std::error_code&);
511 template void BasicSlave::OnWrite<::std::basic_string<char16_t>>(
512  uint16_t, ::std::function<OnWriteSignature<::std::basic_string<char16_t>>>);
513 template void BasicSlave::OnWrite<::std::basic_string<char16_t>>(
514  uint16_t, ::std::function<OnWriteSignature<::std::basic_string<char16_t>>>,
515  ::std::error_code&);
516 
517 // TIME_OF_DAY
518 // TIME_DIFFERENCE
519 // DOMAIN
520 // INTEGER24
521 
522 // REAL64
523 template void BasicSlave::OnRead<double>(
524  uint16_t, uint8_t, ::std::function<OnReadSignature<double>>);
525 template void BasicSlave::OnRead<double>(
526  uint16_t, uint8_t, ::std::function<OnReadSignature<double>>,
527  ::std::error_code&);
528 template void BasicSlave::OnRead<double>(
529  uint16_t, ::std::function<OnReadSignature<double>>);
530 template void BasicSlave::OnRead<double>(
531  uint16_t, ::std::function<OnReadSignature<double>>, ::std::error_code&);
532 template void BasicSlave::OnWrite<double>(
533  uint16_t, uint8_t, ::std::function<OnWriteSignature<double>>);
534 template void BasicSlave::OnWrite<double>(
535  uint16_t, uint8_t, ::std::function<OnWriteSignature<double>>,
536  ::std::error_code&);
537 template void BasicSlave::OnWrite<double>(
538  uint16_t, ::std::function<OnWriteSignature<double>>);
539 template void BasicSlave::OnWrite<double>(
540  uint16_t, ::std::function<OnWriteSignature<double>>, ::std::error_code&);
541 
542 // INTEGER40
543 // INTEGER48
544 // INTEGER56
545 
546 // INTEGER64
547 template void BasicSlave::OnRead<int64_t>(
548  uint16_t, uint8_t, ::std::function<OnReadSignature<int64_t>>);
549 template void BasicSlave::OnRead<int64_t>(
550  uint16_t, uint8_t, ::std::function<OnReadSignature<int64_t>>,
551  ::std::error_code&);
552 template void BasicSlave::OnRead<int64_t>(
553  uint16_t, ::std::function<OnReadSignature<int64_t>>);
554 template void BasicSlave::OnRead<int64_t>(
555  uint16_t, ::std::function<OnReadSignature<int64_t>>, ::std::error_code&);
556 template void BasicSlave::OnWrite<int64_t>(
557  uint16_t, uint8_t, ::std::function<OnWriteSignature<int64_t>>);
558 template void BasicSlave::OnWrite<int64_t>(
559  uint16_t, uint8_t, ::std::function<OnWriteSignature<int64_t>>,
560  ::std::error_code&);
561 template void BasicSlave::OnWrite<int64_t>(
562  uint16_t, ::std::function<OnWriteSignature<int64_t>>);
563 template void BasicSlave::OnWrite<int64_t>(
564  uint16_t, ::std::function<OnWriteSignature<int64_t>>, ::std::error_code&);
565 
566 // UNSIGNED24
567 // UNSIGNED40
568 // UNSIGNED48
569 // UNSIGNED56
570 
571 // UNSIGNED64
572 template void BasicSlave::OnRead<uint64_t>(
573  uint16_t, uint8_t, ::std::function<OnReadSignature<uint64_t>>);
574 template void BasicSlave::OnRead<uint64_t>(
575  uint16_t, uint8_t, ::std::function<OnReadSignature<uint64_t>>,
576  ::std::error_code&);
577 template void BasicSlave::OnRead<uint64_t>(
578  uint16_t, ::std::function<OnReadSignature<uint64_t>>);
579 template void BasicSlave::OnRead<uint64_t>(
580  uint16_t, ::std::function<OnReadSignature<uint64_t>>, ::std::error_code&);
581 template void BasicSlave::OnWrite<uint64_t>(
582  uint16_t, uint8_t, ::std::function<OnWriteSignature<uint64_t>>);
583 template void BasicSlave::OnWrite<uint64_t>(
584  uint16_t, uint8_t, ::std::function<OnWriteSignature<uint64_t>>,
585  ::std::error_code&);
586 template void BasicSlave::OnWrite<uint64_t>(
587  uint16_t, ::std::function<OnWriteSignature<uint64_t>>);
588 template void BasicSlave::OnWrite<uint64_t>(
589  uint16_t, ::std::function<OnWriteSignature<uint64_t>>, ::std::error_code&);
590 
591 #endif // DOXYGEN_SHOULD_SKIP_THIS
592 
593 BasicSlave::Impl_::Impl_(BasicSlave* self_, CONMT* nmt) : self(self_) {
594  nmt->setLgInd<Impl_, &Impl_::OnLgInd>(this);
595 }
596 
597 void
598 BasicSlave::Impl_::OnLgInd(CONMT* nmt, int state) noexcept {
599  // Invoke the default behavior before notifying the implementation.
600  nmt->onLg(state);
601  // Notify the implementation.
602  bool occurred = state == CO_NMT_EC_OCCURRED;
603  self->OnLifeGuarding(occurred);
604  if (on_life_guarding) {
605  auto f = on_life_guarding;
607  f(occurred);
608  }
609 }
610 
611 template <uint16_t N>
612 uint32_t
613 BasicSlave::Impl_::OnDnInd(COSub* sub, COVal<N>& val) noexcept {
614  auto it = dn_ind.find(Key(sub));
615  if (it == dn_ind.end()) return 0;
616  return it->second(sub, static_cast<void*>(&val));
617 }
618 
619 template <uint16_t N>
620 uint32_t
621 BasicSlave::Impl_::OnUpInd(const COSub* sub, COVal<N>& val) noexcept {
622  auto it = up_ind.find(Key(sub));
623  if (it == up_ind.end()) return 0;
624  return it->second(sub, static_cast<void*>(&val));
625 }
626 
627 constexpr uint32_t
628 BasicSlave::Impl_::Key(uint16_t idx, uint8_t subidx) noexcept {
629  return (uint32_t(idx) << 8) | subidx;
630 }
631 
632 uint32_t
633 BasicSlave::Impl_::Key(const COSub* sub) noexcept {
634  assert(sub);
635 
636  return Key(sub->getObj()->getIdx(), sub->getSubidx());
637 }
638 
639 } // namespace canopen
640 
641 } // namespace lely
642 
643 #endif // !LELY_NO_COAPP_SLAVE
A reference to an abstract timer.
Definition: timer.hpp:130
typename ::std::enable_if< detail::is_canopen_type< 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-...
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
Definition: ev.h:29
void lock() final
Blocks until a lock can be obtained for the current execution agent (thread, process, task).
Definition: can_net.hpp:104
This is the internal header file of the C++ CANopen application library.
void unlock() final
Releases the lock held by the execution agent. Throws no exceptions.
Definition: can_net.hpp:109
CONMT * nmt() const noexcept
Returns a pointer to the internal CANopen NMT master/slave service from <lely/co/nmt.hpp>.
Definition: node.cpp:345
A class template mapping CANopen types to C++ types.
Definition: type.hpp:59
This header file is part of the C++ CANopen application library; it contains the CANopen slave declar...
An NMT error control event occurred.
Definition: nmt.h:80
This header file is part of the CANopen library; it contains the C++ interface of the network managem...
Sub-index does not exist.
A mutex wrapper that provides a convenient RAII-style mechanism for releasing a mutex for the duratio...
Definition: mutex.hpp:57
void OnLifeGuarding(::std::function< void(bool)> on_life_guarding)
Registers the function to be invoked when a life guarding event occurs or is resolved.
Definition: slave.cpp:87
::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...
Definition: slave.hpp:610
An opaque CANopen sub-object type.
Definition: obj.hpp:229
This header file is part of the CANopen library; it contains the C++ interface of the object dictiona...
The base class for CANopen slaves.
Definition: slave.hpp:38
Data type does not match, length of service parameter does not match.
Object does not exist in the object dictionary.
typename ::std::conditional< detail::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...
Definition: slave.hpp:633
The internal implementation of the CANopen slave.
Definition: slave.cpp:46
An opaque CANopen NMT master/slave service type.
Definition: nmt.hpp:71
CODev * dev() const noexcept
Returns a pointer to the internal CANopen device from <lely/co/dev.hpp>.
Definition: device.cpp:723
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.
Definition: slave.cpp:78
bool is_canopen_same(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...
Definition: buf.hpp:32
The base class for CANopen nodes.
Definition: node.hpp:115
A CANopen value.
Definition: val.hpp:42
The type of exception thrown when an SDO abort code is received.
Definition: sdo_error.hpp:121
This header file is part of the CANopen library; it contains the C++ interface of the device descript...
A reference to an abstract CAN channel.
Definition: can.hpp:429
typename ::std::enable_if< detail::is_canopen_type< 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...