Lely core libraries 1.9.2
master.cpp
Go to the documentation of this file.
1
24#include "coapp.hpp"
25
26#if !LELY_NO_COAPP_MASTER
27
29#include <lely/coapp/driver.hpp>
30
31#include <algorithm>
32#include <array>
33
34#include <cassert>
35
36#include <lely/co/dev.hpp>
37#include <lely/co/nmt.hpp>
38
39namespace lely {
40
41namespace canopen {
42
45 Impl_(BasicMaster* self, CONMT* nmt);
46
47 void OnNgInd(CONMT* nmt, uint8_t id, int state, int reason) noexcept;
48 void OnBootInd(CONMT* nmt, uint8_t id, uint8_t st, char es) noexcept;
49 void OnCfgInd(CONMT* nmt, uint8_t id, COCSDO* sdo) noexcept;
50
51 BasicMaster* self;
52 ::std::map<uint8_t, Sdo> sdos;
53};
54
55BasicMaster::BasicMaster(aio::TimerBase& timer, aio::CanBusBase& bus,
56 const ::std::string& dcf_txt,
57 const ::std::string& dcf_bin, uint8_t id)
58 : Node(timer, bus, dcf_txt, dcf_bin, id),
59 impl_(new Impl_(this, Node::nmt())) {}
60
61BasicMaster::~BasicMaster() = default;
62
63void
64BasicMaster::Error(uint8_t id) {
65 ::std::lock_guard<BasicLockable> lock(*this);
66
67 if (nmt()->nodeErrInd(id) == -1) throw_errc("Error");
68}
69
70void
71BasicMaster::Error(uint16_t eec, uint8_t er, const uint8_t msef[5]) {
72 ::std::lock_guard<BasicLockable> lock(*this);
73
74 Node::Error(eec, er, msef);
75}
76
77void
79 ::std::lock_guard<BasicLockable> lock(*this);
80
81 Node::RpdoRtr(num);
82}
83
84void
86 ::std::lock_guard<BasicLockable> lock(*this);
87
88 Node::TpdoEvent(num);
89}
90
91::std::chrono::milliseconds
93 ::std::lock_guard<BasicLockable> lock(const_cast<BasicMaster&>(*this));
94
95 return detail::FromTimeout(nmt()->getTimeout());
96}
97
98void
99BasicMaster::SetTimeout(const ::std::chrono::milliseconds& timeout) {
100 ::std::lock_guard<BasicLockable> lock(*this);
101
102 nmt()->setTimeout(detail::ToTimeout(timeout));
103}
104
105void
107 ::std::lock_guard<BasicLockable> lock(*this);
108
109 if (!driver.id() || driver.id() > 0x7f)
110 throw ::std::out_of_range("invalid node-ID: " +
111 ::std::to_string(driver.id()));
112 if (driver.id() == nmt()->getDev()->getId())
113 throw ::std::out_of_range("cannot register node-ID of master: " +
114 ::std::to_string(driver.id()));
115 if (find(driver.id()) != end())
116 throw ::std::out_of_range("node-ID " + ::std::to_string(driver.id()) +
117 " already registered");
118
119 MapType::operator[](driver.id()) = &driver;
120}
121
122void
124 ::std::lock_guard<BasicLockable> lock(*this);
125 assert(find(driver.id()) != end() && find(driver.id())->second == &driver);
126
127 erase(driver.id());
128}
129
130void
131BasicMaster::OnCanError(CanError error) noexcept {
132 for (const auto& it : *this) {
134 it.second->OnCanError(error);
135 }
136}
137
138void
139BasicMaster::OnCanState(CanState new_state, CanState old_state) noexcept {
140 for (const auto& it : *this) {
142 it.second->OnCanState(new_state, old_state);
143 }
144}
145
146void
148 // Abort all ongoing and pending SDO requests unless the master is in the
149 // pre-operational or operational state.
150 if (cs != NmtCommand::ENTER_PREOP && cs != NmtCommand::START) CancelSdo();
151 for (const auto& it : *this) {
153 it.second->OnCommand(cs);
154 }
155}
156
157void
158BasicMaster::OnNodeGuarding(uint8_t id, bool occurred) noexcept {
159 auto it = find(id);
160 if (it != end()) {
162 it->second->OnNodeGuarding(occurred);
163 }
164}
165
166void
167BasicMaster::OnHeartbeat(uint8_t id, bool occurred) noexcept {
168 auto it = find(id);
169 if (it != end()) {
171 it->second->OnHeartbeat(occurred);
172 }
173}
174
175void
176BasicMaster::OnState(uint8_t id, NmtState st) noexcept {
177 // Abort any ongoing or pending SDO requests for the slave, since the master
178 // MAY need the Client-SDO service for the NMT 'boot slave' process.
179 if (st == NmtState::BOOTUP) CancelSdo(id);
180 auto it = find(id);
181 if (it != end()) {
183 it->second->OnState(st);
184 }
185}
186
187void
188BasicMaster::OnBoot(uint8_t id, NmtState st, char es,
189 const ::std::string& what) noexcept {
190 auto it = find(id);
191 if (it != end()) {
193 it->second->OnBoot(st, es, what);
194 }
195}
196
197void
198BasicMaster::OnConfig(uint8_t id) noexcept {
199 auto it = find(id);
200 // If no remote interface is registered for this node, the 'update
201 // configuration' process is considered complete.
202 if (it == end()) {
203 ConfigResult(id, ::std::error_code());
204 return;
205 }
206 // Let the driver perform the configuration update.
208 it->second->OnConfig([=](::std::error_code ec) {
209 ::std::lock_guard<BasicLockable> lock(*this);
210 // Report the result of the 'update configuration' process.
211 ConfigResult(id, ec);
212 });
213}
214
215void
216BasicMaster::ConfigResult(uint8_t id, ::std::error_code ec) noexcept {
217 assert(nmt()->isBooting(id));
218 // Destroy the Client-SDO, since it will be taken over by the master.
219 impl_->sdos.erase(id);
220 // Ignore any errors, since we cannot handle them here.
221 nmt()->cfgRes(id, ec.value());
222}
223
224void
225BasicMaster::OnRpdo(int num, ::std::error_code ec, const void* p,
226 ::std::size_t n) noexcept {
227 for (const auto& it : *this) {
229 it.second->OnRpdo(num, ec, p, n);
230 }
231}
232
233void
234BasicMaster::OnRpdoError(int num, uint16_t eec, uint8_t er) noexcept {
235 for (const auto& it : *this) {
237 it.second->OnRpdoError(num, eec, er);
238 }
239}
240
241void
242BasicMaster::OnTpdo(int num, ::std::error_code ec, const void* p,
243 ::std::size_t n) noexcept {
244 for (const auto& it : *this) {
246 it.second->OnTpdo(num, ec, p, n);
247 }
248}
249
250void
251BasicMaster::OnSync(uint8_t cnt, const time_point& t) noexcept {
252 for (const auto& it : *this) {
254 it.second->OnSync(cnt, t);
255 }
256}
257
258void
259BasicMaster::OnSyncError(uint16_t eec, uint8_t er) noexcept {
260 for (const auto& it : *this) {
262 it.second->OnSyncError(eec, er);
263 }
264}
265
266void
268 const ::std::chrono::system_clock::time_point& abs_time) noexcept {
269 for (const auto& it : *this) {
271 it.second->OnTime(abs_time);
272 }
273}
274
275void
276BasicMaster::OnEmcy(uint8_t id, uint16_t eec, uint8_t er,
277 uint8_t msef[5]) noexcept {
278 auto it = find(id);
279 if (it != end()) {
281 it->second->OnEmcy(eec, er, msef);
282 }
283}
284
285Sdo*
287 if (!id || id > 0x7f)
288 throw ::std::out_of_range("invalid node-ID: " + ::std::to_string(id));
289 // The Client-SDO service only exists in the pre-operational and operational
290 // state.
291 auto st = nmt()->getSt();
292 if (st != CO_NMT_ST_PREOP && st != CO_NMT_ST_START) return nullptr;
293 // During the 'update configuration' step of the NMT 'boot slave' process, a
294 // Client-SDO queue may be available.
295 auto it = impl_->sdos.find(id);
296 if (it != impl_->sdos.end()) return &it->second;
297 // The master needs the Client-SDO service during the NMT 'boot slave'
298 // process.
299 if (nmt()->isBooting(id)) return nullptr;
300 // Return a Client-SDO queue for the default SDO.
301 return &(impl_->sdos[id] = Sdo(nmt()->getNet(), id));
302}
303
304void
306 if (id)
307 impl_->sdos.erase(id);
308 else
309 impl_->sdos.clear();
310}
311
312void
313AsyncMaster::OnCanError(CanError error) noexcept {
314 for (const auto& it : *this) {
315 DriverBase* driver = it.second;
316 auto op = new aio::TaskWrapper([=](::std::error_code ec) {
317 if (!ec) driver->OnCanError(error);
318 });
319 driver->GetExecutor().Post(*op);
320 }
321}
322
323void
324AsyncMaster::OnCanState(CanState new_state, CanState old_state) noexcept {
325 for (const auto& it : *this) {
326 DriverBase* driver = it.second;
327 auto op = new aio::TaskWrapper([=](::std::error_code ec) {
328 if (!ec) driver->OnCanState(new_state, old_state);
329 });
330 driver->GetExecutor().Post(*op);
331 }
332}
333
334void
336 // Abort all ongoing and pending SDO requests unless the master is in the
337 // pre-operational or operational state.
338 if (cs != NmtCommand::ENTER_PREOP && cs != NmtCommand::START) CancelSdo();
339 for (const auto& it : *this) {
340 DriverBase* driver = it.second;
341 auto op = new aio::TaskWrapper([=](::std::error_code ec) {
342 if (!ec) driver->OnCommand(cs);
343 });
344 driver->GetExecutor().Post(*op);
345 }
346}
347
348void
349AsyncMaster::OnNodeGuarding(uint8_t id, bool occurred) noexcept {
350 auto it = find(id);
351 if (it != end()) {
352 DriverBase* driver = it->second;
353 auto op = new aio::TaskWrapper([=](::std::error_code ec) {
354 if (!ec) driver->OnNodeGuarding(occurred);
355 });
356 driver->GetExecutor().Post(*op);
357 }
358}
359
360void
361AsyncMaster::OnHeartbeat(uint8_t id, bool occurred) noexcept {
362 auto it = find(id);
363 if (it != end()) {
364 DriverBase* driver = it->second;
365 auto op = new aio::TaskWrapper([=](::std::error_code ec) {
366 if (!ec) driver->OnHeartbeat(occurred);
367 });
368 driver->GetExecutor().Post(*op);
369 }
370}
371
372void
373AsyncMaster::OnState(uint8_t id, NmtState st) noexcept {
374 // Abort any ongoing or pending SDO requests for the slave, since the master
375 // MAY need the Client-SDO service for the NMT 'boot slave' process.
376 if (st == NmtState::BOOTUP) CancelSdo(id);
377 auto it = find(id);
378 if (it != end()) {
379 DriverBase* driver = it->second;
380 auto op = new aio::TaskWrapper([=](::std::error_code ec) {
381 if (!ec) driver->OnState(st);
382 });
383 driver->GetExecutor().Post(*op);
384 }
385}
386
387void
388AsyncMaster::OnBoot(uint8_t id, NmtState st, char es,
389 const ::std::string& what) noexcept {
390 auto it = find(id);
391 if (it != end()) {
392 DriverBase* driver = it->second;
393 auto op = new aio::TaskWrapper([=](::std::error_code ec) {
394 if (!ec) driver->OnBoot(st, es, what);
395 });
396 driver->GetExecutor().Post(*op);
397 }
398}
399
400void
401AsyncMaster::OnConfig(uint8_t id) noexcept {
402 auto it = find(id);
403 // If no remote interface is registered for this node, the 'update
404 // configuration' process is considered complete.
405 if (it == end()) {
406 ConfigResult(id, ::std::error_code());
407 return;
408 }
409
410 // Let the driver perform the configuration update.
411 DriverBase* driver = it->second;
412 auto op = new aio::TaskWrapper([=](::std::error_code ec) {
413 if (!ec) {
414 driver->OnConfig([=](::std::error_code ec) {
415 ::std::lock_guard<BasicLockable> lock(*this);
416 ConfigResult(id, ec);
417 });
418 } else {
419 ::std::lock_guard<BasicLockable> lock(*this);
420 ConfigResult(id, SdoErrc::ERROR);
421 }
422 });
423 driver->GetExecutor().Post(*op);
424}
425
426void
427AsyncMaster::OnRpdo(int num, ::std::error_code ec, const void* p,
428 ::std::size_t n) noexcept {
429 ::std::array<uint8_t, CAN_MAX_LEN> value;
430 ::std::copy_n(static_cast<const uint8_t*>(p), ::std::min(n, value.size()),
431 value.begin());
432 for (const auto& it : *this) {
433 DriverBase* driver = it.second;
434 // TODO: Ensure lifetime of value.
435 auto op = new aio::TaskWrapper([=](::std::error_code ec_) {
436 if (!ec_) driver->OnRpdo(num, ec, value.data(), value.size());
437 });
438 driver->GetExecutor().Post(*op);
439 }
440}
441
442void
443AsyncMaster::OnRpdoError(int num, uint16_t eec, uint8_t er) noexcept {
444 for (const auto& it : *this) {
445 DriverBase* driver = it.second;
446 auto op = new aio::TaskWrapper([=](::std::error_code ec) {
447 if (!ec) driver->OnRpdoError(num, eec, er);
448 });
449 driver->GetExecutor().Post(*op);
450 }
451}
452
453void
454AsyncMaster::OnTpdo(int num, ::std::error_code ec, const void* p,
455 ::std::size_t n) noexcept {
456 ::std::array<uint8_t, CAN_MAX_LEN> value;
457 ::std::copy_n(static_cast<const uint8_t*>(p), ::std::min(n, value.size()),
458 value.begin());
459 for (const auto& it : *this) {
460 DriverBase* driver = it.second;
461 auto op = new aio::TaskWrapper([=](::std::error_code ec_) {
462 if (!ec_) driver->OnTpdo(num, ec, value.data(), value.size());
463 });
464 driver->GetExecutor().Post(*op);
465 }
466}
467
468void
469AsyncMaster::OnSync(uint8_t cnt, const time_point& t) noexcept {
470 for (const auto& it : *this) {
471 DriverBase* driver = it.second;
472 auto op = new aio::TaskWrapper([=](::std::error_code ec) {
473 if (!ec) driver->OnSync(cnt, t);
474 });
475 driver->GetExecutor().Post(*op);
476 }
477}
478
479void
480AsyncMaster::OnSyncError(uint16_t eec, uint8_t er) noexcept {
481 for (const auto& it : *this) {
482 DriverBase* driver = it.second;
483 auto op = new aio::TaskWrapper([=](::std::error_code ec) {
484 if (!ec) driver->OnSyncError(eec, er);
485 });
486 driver->GetExecutor().Post(*op);
487 }
488}
489
490void
492 const ::std::chrono::system_clock::time_point& abs_time) noexcept {
493 for (const auto& it : *this) {
494 DriverBase* driver = it.second;
495 auto op = new aio::TaskWrapper([=](::std::error_code ec) {
496 if (!ec) driver->OnTime(abs_time);
497 });
498 driver->GetExecutor().Post(*op);
499 }
500}
501
502void
503AsyncMaster::OnEmcy(uint8_t id, uint16_t eec, uint8_t er,
504 uint8_t msef[5]) noexcept {
505 ::std::array<uint8_t, 5> value = {0};
506 ::std::copy_n(msef, value.size(), value.begin());
507 auto it = find(id);
508 if (it != end()) {
509 DriverBase* driver = it->second;
510 auto op = new aio::TaskWrapper([=](::std::error_code ec) mutable {
511 if (!ec) driver->OnEmcy(eec, er, value.data());
512 });
513 driver->GetExecutor().Post(*op);
514 }
515}
516
517BasicMaster::Impl_::Impl_(BasicMaster* self_, CONMT* nmt) : self(self_) {
518 nmt->setNgInd<Impl_, &Impl_::OnNgInd>(this);
519 nmt->setBootInd<Impl_, &Impl_::OnBootInd>(this);
520 nmt->setCfgInd<Impl_, &Impl_::OnCfgInd>(this);
521}
522
523void
524BasicMaster::Impl_::OnNgInd(CONMT* nmt, uint8_t id, int state,
525 int reason) noexcept {
526 // Invoke the default behavior before notifying the implementation.
527 nmt->onNg(id, state, reason);
528 // Only handle node guarding timeout events. State changes are handled by
529 // OnSt().
530 if (reason != CO_NMT_EC_TIMEOUT) return;
531 // Notify the implementation.
532 self->OnNodeGuarding(id, state == CO_NMT_EC_OCCURRED);
533}
534
535void
536BasicMaster::Impl_::OnBootInd(CONMT*, uint8_t id, uint8_t st,
537 char es) noexcept {
538 self->OnBoot(id, static_cast<NmtState>(st), es, es ? co_nmt_es2str(es) : "");
539}
540
541void
542BasicMaster::Impl_::OnCfgInd(CONMT*, uint8_t id, COCSDO* sdo) noexcept {
543 // Create a Client-SDO for the 'update configuration' process.
544 try {
545 sdos[id] = Sdo(sdo);
546 } catch (...) {
547 self->ConfigResult(id, SdoErrc::ERROR);
548 return;
549 }
550 self->OnConfig(id);
551}
552
553} // namespace canopen
554
555} // namespace lely
556
557#endif // !LELY_NO_COAPP_MASTER
This header file is part of the C++ CANopen application library; it contains the timeout conversion f...
An opaque CANopen Client-SDO service type.
Definition: csdo.hpp:156
An opaque CANopen NMT master/slave service type.
Definition: nmt.hpp:70
void OnRpdo(int num, ::std::error_code ec, const void *p, ::std::size_t n) noexcept override
The default implementation queues a notification for all registered drivers.
Definition: master.cpp:427
void OnEmcy(uint8_t id, uint16_t eec, uint8_t er, uint8_t msef[5]) noexcept override
The default implementation queues a notification for the driver registered for node id.
Definition: master.cpp:503
void OnConfig(uint8_t id) noexcept override
The default implementation queues a notification for the driver registered for node id.
Definition: master.cpp:401
void OnBoot(uint8_t id, NmtState st, char es, const ::std::string &what) noexcept override
The default implementation queues a notification for the driver registered for node id.
Definition: master.cpp:388
void OnTpdo(int num, ::std::error_code ec, const void *p, ::std::size_t n) noexcept override
The default implementation queues a notification for all registered drivers.
Definition: master.cpp:454
void OnNodeGuarding(uint8_t id, bool occurred) noexcept override
The default implementation queues a notification for all registered drivers.
Definition: master.cpp:349
void OnSync(uint8_t cnt, const time_point &t) noexcept override
The default implementation queues a notification for all registered drivers.
Definition: master.cpp:469
void OnRpdoError(int num, uint16_t eec, uint8_t er) noexcept override
The default implementation queues a notification for all registered drivers.
Definition: master.cpp:443
void OnHeartbeat(uint8_t id, bool occurred) noexcept override
The default implementation queues a notification for the driver registered for node id.
Definition: master.cpp:361
void OnSyncError(uint16_t eec, uint8_t er) noexcept override
The default implementation queues a notification for all registered drivers.
Definition: master.cpp:480
void OnCanState(CanState new_state, CanState old_state) noexcept override
The default implementation invokes lely::canopen::Node::OnCanState() and queues a notification for ea...
Definition: master.cpp:324
void OnCommand(NmtCommand cs) noexcept override
The default implementation queues a notification for all registered drivers.
Definition: master.cpp:335
void OnState(uint8_t id, NmtState st) noexcept override
The default implementation queues a notification for the driver registered for node id.
Definition: master.cpp:373
void OnCanError(CanError error) noexcept override
The default implementation queues a notification for all registered drivers.
Definition: master.cpp:313
void OnTime(const ::std::chrono::system_clock::time_point &abs_time) noexcept override
The default implementation queues a notification for all registered drivers.
Definition: master.cpp:491
The CANopen master.
Definition: master.hpp:46
void OnSyncError(uint16_t eec, uint8_t er) noexcept override
The default implementation notifies all registered drivers.
Definition: master.cpp:259
void RpdoRtr(int num=0)
Requests the transmission of a PDO.
Definition: master.cpp:78
virtual void OnConfig(uint8_t id) noexcept
The function invoked when the 'update configuration' step is reached during the NMT 'boot slave' proc...
Definition: master.cpp:198
void OnTime(const ::std::chrono::system_clock::time_point &abs_time) noexcept override
The default implementation notifies all registered drivers.
Definition: master.cpp:267
void OnRpdo(int num, ::std::error_code ec, const void *p, ::std::size_t n) noexcept override
The default implementation notifies all registered drivers.
Definition: master.cpp:225
void OnEmcy(uint8_t id, uint16_t eec, uint8_t er, uint8_t msef[5]) noexcept override
The default implementation notifies the driver registered for node id.
Definition: master.cpp:276
void OnHeartbeat(uint8_t id, bool occurred) noexcept override
The default implementation notifies the driver registered for node id.
Definition: master.cpp:167
void Erase(DriverBase &driver)
Unregisters a driver for a remote CANopen node.
Definition: master.cpp:123
void OnSync(uint8_t cnt, const time_point &t) noexcept override
The default implementation notifies all registered drivers.
Definition: master.cpp:251
BasicMaster(aio::TimerBase &timer, aio::CanBusBase &bus, const ::std::string &dcf_txt, const ::std::string &dcf_bin="", uint8_t id=0xff)
Creates a new CANopen master.
Definition: master.cpp:55
void TpdoEvent(int num=0)
Triggers the transmission of an event-driven (asynchronous) PDO.
Definition: master.cpp:85
void Insert(DriverBase &driver)
Registers a driver for a remote CANopen node.
Definition: master.cpp:106
void OnRpdoError(int num, uint16_t eec, uint8_t er) noexcept override
The default implementation notifies all registered drivers.
Definition: master.cpp:234
void Error(uint8_t id)
Indicates the occurrence of an error event on a remote node and triggers the error handling process (...
Definition: master.cpp:64
void OnCanError(CanError error) noexcept override
The default implementation notifies all registered drivers.
Definition: master.cpp:131
::std::chrono::milliseconds GetTimeout() const
Returns the SDO timeout used during the NMT 'boot slave' and 'check configuration' processes.
Definition: master.cpp:92
void OnState(uint8_t id, NmtState st) noexcept override
The default implementation notifies the driver registered for node id.
Definition: master.cpp:176
void OnCommand(NmtCommand cs) noexcept override
The default implementation notifies all registered drivers.
Definition: master.cpp:147
virtual void OnBoot(uint8_t id, NmtState st, char es, const ::std::string &what) noexcept
The function invoked when the NMT 'boot slave' process completes.
Definition: master.cpp:188
void OnTpdo(int num, ::std::error_code ec, const void *p, ::std::size_t n) noexcept override
The default implementation notifies all registered drivers.
Definition: master.cpp:242
void SetTimeout(const ::std::chrono::milliseconds &timeout)
Sets the SDO timeout used during the NMT 'boot slave' and 'check configuration' processes.
Definition: master.cpp:99
void ConfigResult(uint8_t id, ::std::error_code ec) noexcept
Reports the result of the 'update configuration' step to the NMT service.
Definition: master.cpp:216
void CancelSdo(uint8_t id=0)
Aborts any ongoing or pending SDO requests for the specified slave.
Definition: master.cpp:305
void OnCanState(CanState new_state, CanState old_state) noexcept override
The default implementation invokes lely::canopen::Node::OnCanState() and notifies each registered dri...
Definition: master.cpp:139
virtual void OnNodeGuarding(uint8_t id, bool occurred) noexcept
The function invoked when a node guarding timeout event occurs or is resolved.
Definition: master.cpp:158
Sdo * GetSdo(uint8_t id)
Returns a pointer to the default client-SDO service for the given node.
Definition: master.cpp:286
uint8_t id() const noexcept
Returns the node-ID.
Definition: device.cpp:94
The abstract driver interface for a remote CANopen node.
Definition: driver.hpp:33
virtual void OnTpdo(int num, ::std::error_code ec, const void *p, ::std::size_t n) noexcept=0
The function invoked after a Transmit-PDO is sent by the master or an error occurs.
virtual void OnCommand(NmtCommand cs) noexcept=0
The function invoked when an NMT state change occurs on the master.
virtual void OnNodeGuarding(bool occurred) noexcept=0
The function invoked when a node guarding timeout event occurs or is resolved for the remote node.
virtual void OnSync(uint8_t cnt, const Node::time_point &t) noexcept=0
The function invoked when a SYNC message is sent/received by the master.
virtual void OnHeartbeat(bool occurred) noexcept=0
The function invoked when a heartbeat timeout event occurs or is resolved for the remote node.
virtual void OnConfig(::std::function< void(::std::error_code ec)> res) noexcept=0
The function invoked when the 'update configuration' step is reached during the NMT 'boot slave' proc...
virtual void OnRpdoError(int num, uint16_t eec, uint8_t er) noexcept=0
The function invoked when a Receive-PDO length mismatch or timeout error occurs on the master.
virtual void OnCanError(CanError error) noexcept=0
The function invoked when an error is detected on the CAN bus.
virtual aio::ExecutorBase GetExecutor() const noexcept=0
Returns the executor used to execute event handlers for this driver, including SDO confirmation funct...
virtual void OnTime(const ::std::chrono::system_clock::time_point &abs_time) noexcept=0
The function invoked when a TIME message is received by the master.
virtual void OnSyncError(uint16_t eec, uint8_t er) noexcept=0
The function invoked when the data length of a received SYNC message does not match.
virtual void OnState(NmtState st) noexcept=0
The function invoked when an NMT state change or boot-up event is detected for the remote node by the...
virtual uint8_t id() const noexcept=0
Returns the node-ID.
virtual void OnEmcy(uint16_t eec, uint8_t er, uint8_t msef[5]) noexcept=0
The function invoked when an EMCY message is received from the remote node.
virtual void OnBoot(NmtState st, char es, const ::std::string &what) noexcept=0
The function invoked when the NMT 'boot slave' process completes for the remote node.
virtual void OnRpdo(int num, ::std::error_code ec, const void *p, ::std::size_t n) noexcept=0
The function invoked when a Receive-PDO is processed by the master.
virtual void OnCanState(CanState new_state, CanState old_state) noexcept=0
The function invoked when a CAN bus state change is detected.
The base class for CANopen nodes.
Definition: node.hpp:109
void TpdoEvent(int num=0)
Triggers the transmission of an event-driven (asynchronous) PDO.
Definition: node.cpp:156
CONMT * nmt() const noexcept
Returns a pointer to the internal CANopen NMT master/slave service from <lely/co/nmt....
Definition: node.cpp:137
void RpdoRtr(int num=0)
Requests the transmission of a PDO.
Definition: node.cpp:147
virtual void lock() final override
Blocks until a lock can be obtained for the current execution agent (thread, process,...
Definition: node.cpp:114
The Client-SDO queue.
Definition: sdo.hpp:48
A mutex wrapper that provides a convenient RAII-style mechanism for releasing a mutex for the duratio...
Definition: mutex.hpp:43
The type of objects thrown as exceptions to report a system error with an associated error code.
Definition: exception.hpp:54
This header file is part of the CANopen library; it contains the C++ interface of the device descript...
This header file is part of the C++ CANopen application library; it contains the remote node driver i...
inline ::std::chrono::milliseconds FromTimeout(int timeout)
Converts an SDO timeout to a duration.
Definition: chrono.hpp:38
int ToTimeout(const ::std::chrono::duration< Rep, Period > &d)
Converts a duration to an SDO timeout.
Definition: chrono.hpp:46
NmtState
The NMT states.
Definition: node.hpp:50
@ ERROR
General error.
NmtCommand
The NMT command specifiers.
Definition: node.hpp:36
@ ENTER_PREOP
Enter pre-operational.
Global namespace for the Lely Industries N.V. libraries.
Definition: buf.hpp:32
@ CO_NMT_EC_OCCURRED
An NMT error control event occurred.
Definition: nmt.h:80
const char * co_nmt_es2str(char es)
Returns a pointer to a string describing an NMT boot error status.
Definition: nmt.c:679
#define CO_NMT_ST_PREOP
The NMT state 'pre-operational'.
Definition: nmt.h:70
#define CO_NMT_ST_START
The NMT state 'operational'.
Definition: nmt.h:61
@ CO_NMT_EC_TIMEOUT
An NMT error control timeout event.
Definition: nmt.h:87
This header file is part of the CANopen library; it contains the C++ interface of the network managem...
This is the internal header file of the C++ CANopen application library.
The internal implementation of the CANopen master.
Definition: master.cpp:44