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 
39 namespace lely {
40 
41 namespace 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 
55 BasicMaster::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 
61 BasicMaster::~BasicMaster() = default;
62 
63 void
64 BasicMaster::Error(uint8_t id) {
65  ::std::lock_guard<BasicLockable> lock(*this);
66 
67  if (nmt()->nodeErrInd(id) == -1) throw_errc("Error");
68 }
69 
70 void
71 BasicMaster::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 
77 void
79  ::std::lock_guard<BasicLockable> lock(*this);
80 
81  Node::RpdoRtr(num);
82 }
83 
84 void
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 
98 void
99 BasicMaster::SetTimeout(const ::std::chrono::milliseconds& timeout) {
100  ::std::lock_guard<BasicLockable> lock(*this);
101 
102  nmt()->setTimeout(detail::ToTimeout(timeout));
103 }
104 
105 void
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 
122 void
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 
130 void
131 BasicMaster::OnCanError(CanError error) noexcept {
132  for (const auto& it : *this) {
134  it.second->OnCanError(error);
135  }
136 }
137 
138 void
139 BasicMaster::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 
146 void
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 
157 void
158 BasicMaster::OnNodeGuarding(uint8_t id, bool occurred) noexcept {
159  auto it = find(id);
160  if (it != end()) {
162  it->second->OnNodeGuarding(occurred);
163  }
164 }
165 
166 void
167 BasicMaster::OnHeartbeat(uint8_t id, bool occurred) noexcept {
168  auto it = find(id);
169  if (it != end()) {
171  it->second->OnHeartbeat(occurred);
172  }
173 }
174 
175 void
176 BasicMaster::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 
187 void
188 BasicMaster::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 
197 void
198 BasicMaster::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 
215 void
216 BasicMaster::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 
224 void
225 BasicMaster::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 
233 void
234 BasicMaster::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 
241 void
242 BasicMaster::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 
250 void
251 BasicMaster::OnSync(uint8_t cnt, const time_point& t) noexcept {
252  for (const auto& it : *this) {
254  it.second->OnSync(cnt, t);
255  }
256 }
257 
258 void
259 BasicMaster::OnSyncError(uint16_t eec, uint8_t er) noexcept {
260  for (const auto& it : *this) {
262  it.second->OnSyncError(eec, er);
263  }
264 }
265 
266 void
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 
275 void
276 BasicMaster::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 
285 Sdo*
286 BasicMaster::GetSdo(uint8_t id) {
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 
304 void
306  if (id)
307  impl_->sdos.erase(id);
308  else
309  impl_->sdos.clear();
310 }
311 
312 void
313 AsyncMaster::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 
323 void
324 AsyncMaster::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 
334 void
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 
348 void
349 AsyncMaster::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 
360 void
361 AsyncMaster::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 
372 void
373 AsyncMaster::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 
387 void
388 AsyncMaster::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 
400 void
401 AsyncMaster::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 
426 void
427 AsyncMaster::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 
442 void
443 AsyncMaster::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 
453 void
454 AsyncMaster::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 
468 void
469 AsyncMaster::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 
479 void
480 AsyncMaster::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 
490 void
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 
502 void
503 AsyncMaster::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 
517 BasicMaster::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 
523 void
524 BasicMaster::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 
535 void
536 BasicMaster::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 
541 void
542 BasicMaster::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
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 OnConfig(uint8_t id) noexcept
The function invoked when the &#39;update configuration&#39; step is reached during the NMT &#39;boot slave&#39; proc...
Definition: master.cpp:198
void OnSyncError(uint16_t eec, uint8_t er) noexcept override
The default implementation notifies all registered drivers.
Definition: master.cpp:259
The CANopen master.
Definition: master.hpp:46
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.
#define CO_NMT_ST_START
The NMT state &#39;operational&#39;.
Definition: nmt.h:61
void CancelSdo(uint8_t id=0)
Aborts any ongoing or pending SDO requests for the specified slave.
Definition: master.cpp:305
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
void OnState(uint8_t id, NmtState st) noexcept override
The default implementation notifies the driver registered for node id.
Definition: master.cpp:176
An NMT error control event occurred.
Definition: nmt.h:80
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
NmtCommand
The NMT command specifiers.
Definition: node.hpp:36
virtual void OnNodeGuarding(bool occurred) noexcept=0
The function invoked when a node guarding timeout event occurs or is resolved for the remote node...
const char * co_nmt_es2str(char es)
Returns a pointer to a string describing an NMT boot error status.
Definition: nmt.c:679
virtual uint8_t id() const noexcept=0
Returns the node-ID.
CONMT * nmt() const noexcept
Returns a pointer to the internal CANopen NMT master/slave service from <lely/co/nmt.hpp>.
Definition: node.cpp:137
The abstract driver interface for a remote CANopen node.
Definition: driver.hpp:33
void SetTimeout(const ::std::chrono::milliseconds &timeout)
Sets the SDO timeout used during the NMT &#39;boot slave&#39; and &#39;check configuration&#39; processes.
Definition: master.cpp:99
An opaque CANopen Client-SDO service type.
Definition: csdo.hpp:156
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
virtual void OnConfig(::std::function< void(::std::error_code ec)> res) noexcept=0
The function invoked when the &#39;update configuration&#39; step is reached during the NMT &#39;boot slave&#39; proc...
void OnSync(uint8_t cnt, const time_point &t) noexcept override
The default implementation notifies all registered drivers.
Definition: master.cpp:251
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.
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
virtual void OnCommand(NmtCommand cs) noexcept=0
The function invoked when an NMT state change occurs on the master.
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
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.
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
virtual void OnCanState(CanState new_state, CanState old_state) noexcept=0
The function invoked when a CAN bus state change is detected.
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.
This header file is part of the CANopen library; it contains the C++ interface of the network managem...
This header file is part of the CANopen library; it contains the C++ interface of the device descript...
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
virtual void OnBoot(uint8_t id, NmtState st, char es, const ::std::string &what) noexcept
The function invoked when the NMT &#39;boot slave&#39; process completes.
Definition: master.cpp:188
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
The internal implementation of the CANopen master.
Definition: master.cpp:44
void OnNodeGuarding(uint8_t id, bool occurred) noexcept override
The default implementation queues a notification for all registered drivers.
Definition: master.cpp:349
#define CO_NMT_ST_PREOP
The NMT state &#39;pre-operational&#39;.
Definition: nmt.h:70
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
inline ::std::chrono::milliseconds FromTimeout(int timeout)
Converts an SDO timeout to a duration.
Definition: chrono.hpp:38
void OnCommand(NmtCommand cs) noexcept override
The default implementation notifies all registered drivers.
Definition: master.cpp:147
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...
void RpdoRtr(int num=0)
Requests the transmission of a PDO.
Definition: master.cpp:78
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 C++ CANopen application library; it contains the remote node driver i...
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
void OnCanError(CanError error) noexcept override
The default implementation notifies all registered drivers.
Definition: master.cpp:131
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
virtual void OnBoot(NmtState st, char es, const ::std::string &what) noexcept=0
The function invoked when the NMT &#39;boot slave&#39; process completes for the remote node.
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...
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
This header file is part of the C++ CANopen application library; it contains the timeout conversion f...
void TpdoEvent(int num=0)
Triggers the transmission of an event-driven (asynchronous) PDO.
Definition: master.cpp:85
virtual void OnCanError(CanError error) noexcept=0
The function invoked when an error is detected on the CAN bus.
virtual void OnHeartbeat(bool occurred) noexcept=0
The function invoked when a heartbeat timeout event occurs or is resolved for the remote node...
int ToTimeout(const ::std::chrono::duration< Rep, Period > &d)
Converts a duration to an SDO timeout.
Definition: chrono.hpp:46
An NMT error control timeout event.
Definition: nmt.h:87
This is the internal header file of the C++ CANopen application library.
void OnCommand(NmtCommand cs) noexcept override
The default implementation queues a notification for all registered drivers.
Definition: master.cpp:335
void Insert(DriverBase &driver)
Registers a driver for a remote CANopen node.
Definition: master.cpp:106
void OnSyncError(uint16_t eec, uint8_t er) noexcept override
The default implementation queues a notification for all registered drivers.
Definition: master.cpp:480
virtual aio::ExecutorBase GetExecutor() const noexcept=0
Returns the executor used to execute event handlers for this driver, including SDO confirmation funct...
void RpdoRtr(int num=0)
Requests the transmission of a PDO.
Definition: node.cpp:147
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.
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 OnHeartbeat(uint8_t id, bool occurred) noexcept override
The default implementation notifies the driver registered for node id.
Definition: master.cpp:167
::std::chrono::milliseconds GetTimeout() const
Returns the SDO timeout used during the NMT &#39;boot slave&#39; and &#39;check configuration&#39; processes...
Definition: master.cpp:92
NmtState
The NMT states.
Definition: node.hpp:50
An opaque CANopen NMT master/slave service type.
Definition: nmt.hpp:70
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
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
A mutex wrapper that provides a convenient RAII-style mechanism for releasing a mutex for the duratio...
Definition: mutex.hpp:43
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
virtual void lock() final override
Blocks until a lock can be obtained for the current execution agent (thread, process, task).
Definition: node.cpp:114
The Client-SDO queue.
Definition: sdo.hpp:48
Global namespace for the Lely Industries N.V. libraries.
Definition: buf.hpp:32
uint8_t id() const noexcept
Returns the node-ID.
Definition: device.cpp:94
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 ConfigResult(uint8_t id, ::std::error_code ec) noexcept
Reports the result of the &#39;update configuration&#39; step to the NMT service.
Definition: master.cpp:216
Sdo * GetSdo(uint8_t id)
Returns a pointer to the default client-SDO service for the given node.
Definition: master.cpp:286
The base class for CANopen nodes.
Definition: node.hpp:109
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 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 OnRpdoError(int num, uint16_t eec, uint8_t er) noexcept override
The default implementation notifies all registered drivers.
Definition: master.cpp:234
void Erase(DriverBase &driver)
Unregisters a driver for a remote CANopen node.
Definition: master.cpp:123
void TpdoEvent(int num=0)
Triggers the transmission of an event-driven (asynchronous) PDO.
Definition: node.cpp:156