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
41namespace lely {
42
43namespace canopen {
44
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
82BasicSlave::~BasicSlave() = default;
83
84template <class T>
85typename ::std::enable_if<is_canopen<T>::value>::type
86BasicSlave::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
93namespace {
94
95template <class T, class F>
96uint32_t
97OnUpInd(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
125template <class T>
126typename ::std::enable_if<is_canopen<T>::value>::type
127BasicSlave::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))) {
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
168template <class T>
169typename ::std::enable_if<is_canopen<T>::value>::type
170BasicSlave::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
175template <class T>
176typename ::std::enable_if<is_canopen<T>::value>::type
177BasicSlave::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
183template <class T>
184typename ::std::enable_if<is_canopen<T>::value>::type
185BasicSlave::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
192namespace {
193
194template <class T, class F>
195typename ::std::enable_if<is_canopen_basic<T>::value, uint32_t>::type
196OnDnInd(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
220template <class T, class F>
221typename ::std::enable_if<!is_canopen_basic<T>::value, uint32_t>::type
222OnDnInd(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
252template <class T>
253typename ::std::enable_if<is_canopen<T>::value>::type
254BasicSlave::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))) {
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
294template <class T>
295typename ::std::enable_if<is_canopen<T>::value>::type
296BasicSlave::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
301template <class T>
302typename ::std::enable_if<is_canopen<T>::value>::type
303BasicSlave::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
312template void BasicSlave::OnRead<bool>(uint16_t, uint8_t,
313 ::std::function<OnReadSignature<bool>>);
314template void BasicSlave::OnRead<bool>(uint16_t, uint8_t,
315 ::std::function<OnReadSignature<bool>>,
316 ::std::error_code&);
317template void BasicSlave::OnRead<bool>(uint16_t,
318 ::std::function<OnReadSignature<bool>>);
319template void BasicSlave::OnRead<bool>(uint16_t,
320 ::std::function<OnReadSignature<bool>>,
321 ::std::error_code&);
322template void BasicSlave::OnWrite<bool>(
323 uint16_t, uint8_t, ::std::function<OnWriteSignature<bool>>);
324template void BasicSlave::OnWrite<bool>(uint16_t, uint8_t,
325 ::std::function<OnWriteSignature<bool>>,
326 ::std::error_code&);
327template void BasicSlave::OnWrite<bool>(
328 uint16_t, ::std::function<OnWriteSignature<bool>>);
329template void BasicSlave::OnWrite<bool>(uint16_t,
330 ::std::function<OnWriteSignature<bool>>,
331 ::std::error_code&);
332
333// INTEGER8
334template void BasicSlave::OnRead<int8_t>(
335 uint16_t, uint8_t, ::std::function<OnReadSignature<int8_t>>);
336template void BasicSlave::OnRead<int8_t>(
337 uint16_t, uint8_t, ::std::function<OnReadSignature<int8_t>>,
338 ::std::error_code&);
339template void BasicSlave::OnRead<int8_t>(
340 uint16_t, ::std::function<OnReadSignature<int8_t>>);
341template void BasicSlave::OnRead<int8_t>(
342 uint16_t, ::std::function<OnReadSignature<int8_t>>, ::std::error_code&);
343template void BasicSlave::OnWrite<int8_t>(
344 uint16_t, uint8_t, ::std::function<OnWriteSignature<int8_t>>);
345template void BasicSlave::OnWrite<int8_t>(
346 uint16_t, uint8_t, ::std::function<OnWriteSignature<int8_t>>,
347 ::std::error_code&);
348template void BasicSlave::OnWrite<int8_t>(
349 uint16_t, ::std::function<OnWriteSignature<int8_t>>);
350template void BasicSlave::OnWrite<int8_t>(
351 uint16_t, ::std::function<OnWriteSignature<int8_t>>, ::std::error_code&);
352
353// INTEGER16
354template void BasicSlave::OnRead<int16_t>(
355 uint16_t, uint8_t, ::std::function<OnReadSignature<int16_t>>);
356template void BasicSlave::OnRead<int16_t>(
357 uint16_t, uint8_t, ::std::function<OnReadSignature<int16_t>>,
358 ::std::error_code&);
359template void BasicSlave::OnRead<int16_t>(
360 uint16_t, ::std::function<OnReadSignature<int16_t>>);
361template void BasicSlave::OnRead<int16_t>(
362 uint16_t, ::std::function<OnReadSignature<int16_t>>, ::std::error_code&);
363template void BasicSlave::OnWrite<int16_t>(
364 uint16_t, uint8_t, ::std::function<OnWriteSignature<int16_t>>);
365template void BasicSlave::OnWrite<int16_t>(
366 uint16_t, uint8_t, ::std::function<OnWriteSignature<int16_t>>,
367 ::std::error_code&);
368template void BasicSlave::OnWrite<int16_t>(
369 uint16_t, ::std::function<OnWriteSignature<int16_t>>);
370template void BasicSlave::OnWrite<int16_t>(
371 uint16_t, ::std::function<OnWriteSignature<int16_t>>, ::std::error_code&);
372
373// INTEGER32
374template void BasicSlave::OnRead<int32_t>(
375 uint16_t, uint8_t, ::std::function<OnReadSignature<int32_t>>);
376template void BasicSlave::OnRead<int32_t>(
377 uint16_t, uint8_t, ::std::function<OnReadSignature<int32_t>>,
378 ::std::error_code&);
379template void BasicSlave::OnRead<int32_t>(
380 uint16_t, ::std::function<OnReadSignature<int32_t>>);
381template void BasicSlave::OnRead<int32_t>(
382 uint16_t, ::std::function<OnReadSignature<int32_t>>, ::std::error_code&);
383template void BasicSlave::OnWrite<int32_t>(
384 uint16_t, uint8_t, ::std::function<OnWriteSignature<int32_t>>);
385template void BasicSlave::OnWrite<int32_t>(
386 uint16_t, uint8_t, ::std::function<OnWriteSignature<int32_t>>,
387 ::std::error_code&);
388template void BasicSlave::OnWrite<int32_t>(
389 uint16_t, ::std::function<OnWriteSignature<int32_t>>);
390template void BasicSlave::OnWrite<int32_t>(
391 uint16_t, ::std::function<OnWriteSignature<int32_t>>, ::std::error_code&);
392
393// UNSIGNED8
394template void BasicSlave::OnRead<uint8_t>(
395 uint16_t, uint8_t, ::std::function<OnReadSignature<uint8_t>>);
396template void BasicSlave::OnRead<uint8_t>(
397 uint16_t, uint8_t, ::std::function<OnReadSignature<uint8_t>>,
398 ::std::error_code&);
399template void BasicSlave::OnRead<uint8_t>(
400 uint16_t, ::std::function<OnReadSignature<uint8_t>>);
401template void BasicSlave::OnRead<uint8_t>(
402 uint16_t, ::std::function<OnReadSignature<uint8_t>>, ::std::error_code&);
403template void BasicSlave::OnWrite<uint8_t>(
404 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint8_t>>);
405template void BasicSlave::OnWrite<uint8_t>(
406 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint8_t>>,
407 ::std::error_code&);
408template void BasicSlave::OnWrite<uint8_t>(
409 uint16_t, ::std::function<OnWriteSignature<uint8_t>>);
410template void BasicSlave::OnWrite<uint8_t>(
411 uint16_t, ::std::function<OnWriteSignature<uint8_t>>, ::std::error_code&);
412
413// UNSIGNED16
414template void BasicSlave::OnRead<uint16_t>(
415 uint16_t, uint8_t, ::std::function<OnReadSignature<uint16_t>>);
416template void BasicSlave::OnRead<uint16_t>(
417 uint16_t, uint8_t, ::std::function<OnReadSignature<uint16_t>>,
418 ::std::error_code&);
419template void BasicSlave::OnRead<uint16_t>(
420 uint16_t, ::std::function<OnReadSignature<uint16_t>>);
421template void BasicSlave::OnRead<uint16_t>(
422 uint16_t, ::std::function<OnReadSignature<uint16_t>>, ::std::error_code&);
423template void BasicSlave::OnWrite<uint16_t>(
424 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint16_t>>);
425template void BasicSlave::OnWrite<uint16_t>(
426 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint16_t>>,
427 ::std::error_code&);
428template void BasicSlave::OnWrite<uint16_t>(
429 uint16_t, ::std::function<OnWriteSignature<uint16_t>>);
430template void BasicSlave::OnWrite<uint16_t>(
431 uint16_t, ::std::function<OnWriteSignature<uint16_t>>, ::std::error_code&);
432
433// UNSIGNED32
434template void BasicSlave::OnRead<uint32_t>(
435 uint16_t, uint8_t, ::std::function<OnReadSignature<uint32_t>>);
436template void BasicSlave::OnRead<uint32_t>(
437 uint16_t, uint8_t, ::std::function<OnReadSignature<uint32_t>>,
438 ::std::error_code&);
439template void BasicSlave::OnRead<uint32_t>(
440 uint16_t, ::std::function<OnReadSignature<uint32_t>>);
441template void BasicSlave::OnRead<uint32_t>(
442 uint16_t, ::std::function<OnReadSignature<uint32_t>>, ::std::error_code&);
443template void BasicSlave::OnWrite<uint32_t>(
444 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint32_t>>);
445template void BasicSlave::OnWrite<uint32_t>(
446 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint32_t>>,
447 ::std::error_code&);
448template void BasicSlave::OnWrite<uint32_t>(
449 uint16_t, ::std::function<OnWriteSignature<uint32_t>>);
450template void BasicSlave::OnWrite<uint32_t>(
451 uint16_t, ::std::function<OnWriteSignature<uint32_t>>, ::std::error_code&);
452
453// REAL32
454template void BasicSlave::OnRead<float>(
455 uint16_t, uint8_t, ::std::function<OnReadSignature<float>>);
456template void BasicSlave::OnRead<float>(uint16_t, uint8_t,
457 ::std::function<OnReadSignature<float>>,
458 ::std::error_code&);
459template void BasicSlave::OnRead<float>(
460 uint16_t, ::std::function<OnReadSignature<float>>);
461template void BasicSlave::OnRead<float>(uint16_t,
462 ::std::function<OnReadSignature<float>>,
463 ::std::error_code&);
464template void BasicSlave::OnWrite<float>(
465 uint16_t, uint8_t, ::std::function<OnWriteSignature<float>>);
466template void BasicSlave::OnWrite<float>(
467 uint16_t, uint8_t, ::std::function<OnWriteSignature<float>>,
468 ::std::error_code&);
469template void BasicSlave::OnWrite<float>(
470 uint16_t, ::std::function<OnWriteSignature<float>>);
471template void BasicSlave::OnWrite<float>(
472 uint16_t, ::std::function<OnWriteSignature<float>>, ::std::error_code&);
473
474// VISIBLE_STRING
475template void BasicSlave::OnRead<::std::string>(
476 uint16_t, uint8_t, ::std::function<OnReadSignature<::std::string>>);
477template void BasicSlave::OnRead<::std::string>(
478 uint16_t, uint8_t, ::std::function<OnReadSignature<::std::string>>,
479 ::std::error_code&);
480template void BasicSlave::OnRead<::std::string>(
481 uint16_t, ::std::function<OnReadSignature<::std::string>>);
482template void BasicSlave::OnRead<::std::string>(
483 uint16_t, ::std::function<OnReadSignature<::std::string>>,
484 ::std::error_code&);
485template void BasicSlave::OnWrite<::std::string>(
486 uint16_t, uint8_t, ::std::function<OnWriteSignature<::std::string>>);
487template void BasicSlave::OnWrite<::std::string>(
488 uint16_t, uint8_t, ::std::function<OnWriteSignature<::std::string>>,
489 ::std::error_code&);
490template void BasicSlave::OnWrite<::std::string>(
491 uint16_t, ::std::function<OnWriteSignature<::std::string>>);
492template void BasicSlave::OnWrite<::std::string>(
493 uint16_t, ::std::function<OnWriteSignature<::std::string>>,
494 ::std::error_code&);
495
496// OCTET_STRING
497template void BasicSlave::OnRead<::std::vector<uint8_t>>(
498 uint16_t, uint8_t,
499 ::std::function<OnReadSignature<::std::vector<uint8_t>>>);
500template void BasicSlave::OnRead<::std::vector<uint8_t>>(
501 uint16_t, uint8_t, ::std::function<OnReadSignature<::std::vector<uint8_t>>>,
502 ::std::error_code&);
503template void BasicSlave::OnRead<::std::vector<uint8_t>>(
504 uint16_t, ::std::function<OnReadSignature<::std::vector<uint8_t>>>);
505template void BasicSlave::OnRead<::std::vector<uint8_t>>(
506 uint16_t, ::std::function<OnReadSignature<::std::vector<uint8_t>>>,
507 ::std::error_code&);
508template void BasicSlave::OnWrite<::std::vector<uint8_t>>(
509 uint16_t, uint8_t,
510 ::std::function<OnWriteSignature<::std::vector<uint8_t>>>);
511template void BasicSlave::OnWrite<::std::vector<uint8_t>>(
512 uint16_t, uint8_t,
513 ::std::function<OnWriteSignature<::std::vector<uint8_t>>>,
514 ::std::error_code&);
515template void BasicSlave::OnWrite<::std::vector<uint8_t>>(
516 uint16_t, ::std::function<OnWriteSignature<::std::vector<uint8_t>>>);
517template 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
522template void BasicSlave::OnRead<::std::basic_string<char16_t>>(
523 uint16_t, uint8_t,
524 ::std::function<OnReadSignature<::std::basic_string<char16_t>>>);
525template 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&);
529template void BasicSlave::OnRead<::std::basic_string<char16_t>>(
530 uint16_t, ::std::function<OnReadSignature<::std::basic_string<char16_t>>>);
531template void BasicSlave::OnRead<::std::basic_string<char16_t>>(
532 uint16_t, ::std::function<OnReadSignature<::std::basic_string<char16_t>>>,
533 ::std::error_code&);
534template void BasicSlave::OnWrite<::std::basic_string<char16_t>>(
535 uint16_t, uint8_t,
536 ::std::function<OnWriteSignature<::std::basic_string<char16_t>>>);
537template 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&);
541template void BasicSlave::OnWrite<::std::basic_string<char16_t>>(
542 uint16_t, ::std::function<OnWriteSignature<::std::basic_string<char16_t>>>);
543template 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
553template void BasicSlave::OnRead<double>(
554 uint16_t, uint8_t, ::std::function<OnReadSignature<double>>);
555template void BasicSlave::OnRead<double>(
556 uint16_t, uint8_t, ::std::function<OnReadSignature<double>>,
557 ::std::error_code&);
558template void BasicSlave::OnRead<double>(
559 uint16_t, ::std::function<OnReadSignature<double>>);
560template void BasicSlave::OnRead<double>(
561 uint16_t, ::std::function<OnReadSignature<double>>, ::std::error_code&);
562template void BasicSlave::OnWrite<double>(
563 uint16_t, uint8_t, ::std::function<OnWriteSignature<double>>);
564template void BasicSlave::OnWrite<double>(
565 uint16_t, uint8_t, ::std::function<OnWriteSignature<double>>,
566 ::std::error_code&);
567template void BasicSlave::OnWrite<double>(
568 uint16_t, ::std::function<OnWriteSignature<double>>);
569template void BasicSlave::OnWrite<double>(
570 uint16_t, ::std::function<OnWriteSignature<double>>, ::std::error_code&);
571
572// INTEGER40
573// INTEGER48
574// INTEGER56
575
576// INTEGER64
577template void BasicSlave::OnRead<int64_t>(
578 uint16_t, uint8_t, ::std::function<OnReadSignature<int64_t>>);
579template void BasicSlave::OnRead<int64_t>(
580 uint16_t, uint8_t, ::std::function<OnReadSignature<int64_t>>,
581 ::std::error_code&);
582template void BasicSlave::OnRead<int64_t>(
583 uint16_t, ::std::function<OnReadSignature<int64_t>>);
584template void BasicSlave::OnRead<int64_t>(
585 uint16_t, ::std::function<OnReadSignature<int64_t>>, ::std::error_code&);
586template void BasicSlave::OnWrite<int64_t>(
587 uint16_t, uint8_t, ::std::function<OnWriteSignature<int64_t>>);
588template void BasicSlave::OnWrite<int64_t>(
589 uint16_t, uint8_t, ::std::function<OnWriteSignature<int64_t>>,
590 ::std::error_code&);
591template void BasicSlave::OnWrite<int64_t>(
592 uint16_t, ::std::function<OnWriteSignature<int64_t>>);
593template 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
602template void BasicSlave::OnRead<uint64_t>(
603 uint16_t, uint8_t, ::std::function<OnReadSignature<uint64_t>>);
604template void BasicSlave::OnRead<uint64_t>(
605 uint16_t, uint8_t, ::std::function<OnReadSignature<uint64_t>>,
606 ::std::error_code&);
607template void BasicSlave::OnRead<uint64_t>(
608 uint16_t, ::std::function<OnReadSignature<uint64_t>>);
609template void BasicSlave::OnRead<uint64_t>(
610 uint16_t, ::std::function<OnReadSignature<uint64_t>>, ::std::error_code&);
611template void BasicSlave::OnWrite<uint64_t>(
612 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint64_t>>);
613template void BasicSlave::OnWrite<uint64_t>(
614 uint16_t, uint8_t, ::std::function<OnWriteSignature<uint64_t>>,
615 ::std::error_code&);
616template void BasicSlave::OnWrite<uint64_t>(
617 uint16_t, ::std::function<OnWriteSignature<uint64_t>>);
618template void BasicSlave::OnWrite<uint64_t>(
619 uint16_t, ::std::function<OnWriteSignature<uint64_t>>, ::std::error_code&);
620
621#endif // DOXYGEN_SHOULD_SKIP_THIS
622
623void
624BasicSlave::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
629BasicSlave::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
643void
644BasicSlave::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
658constexpr uint32_t
659BasicSlave::Impl_::Key(uint16_t idx, uint8_t subidx) noexcept {
660 return (uint32_t(idx) << 8) | subidx;
661}
662
663uint32_t
664BasicSlave::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
The base class for CANopen slaves.
Definition: slave.hpp:38
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
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-...
Definition: slave.cpp:86
::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:627
typename ::std::conditional< 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:650
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...
Definition: slave.cpp:185
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
__co_dev * dev() const noexcept
Returns a pointer to the internal CANopen device from <lely/co/dev.hpp>.
Definition: device.cpp:828
The base class for CANopen nodes.
Definition: node.hpp:116
__co_nmt * nmt() const noexcept
Returns a pointer to the internal CANopen NMT master/slave service from <lely/co/nmt....
Definition: node.cpp:434
The type of exception thrown when an SDO abort code is received.
Definition: sdo_error.hpp:121
A reference to an abstract CAN channel.
Definition: can.hpp:430
void lock() final
Blocks until a lock can be obtained for the current execution agent (thread, process,...
Definition: can_net.hpp:104
A reference to an abstract timer.
Definition: timer.hpp:130
This header file is part of the CANopen library; it contains the device description declarations.
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
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_unsigned8_t co_dev_get_netid(const co_dev_t *dev)
Returns the network-ID of a CANopen device.
Definition: dev.c:174
This is the internal header file of the C++ CANopen application library.
This header file is part of the CANopen library; it contains the Service Data Object (SDO) declaratio...
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
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
#define CO_SDO_AC_NO_DATA
SDO abort code: No data available.
Definition: sdo.h:175
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
Definition: ev.h:29
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.
@ 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.
This header file is part of the CANopen library; it contains the network management (NMT) declaration...
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
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_NMT_EC_OCCURRED
An NMT error control event occurred.
Definition: nmt.h:80
This header file is part of the CANopen library; it contains the object dictionary declarations.
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
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_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
Definition: obj.c:164
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
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
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
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
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_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
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
This header file is part of the C++ CANopen application library; it contains the CANopen slave declar...
A CANopen NMT master/slave service.
Definition: nmt.c:148
A CANopen sub-object.
Definition: obj.h:53
A CANopen SDO upload/download request.
Definition: sdo.h:181
The internal implementation of the CANopen slave.
Definition: slave.cpp:46
A class template mapping CANopen types to C and C++ types.
Definition: type_traits.hpp:98