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