Lely core libraries 1.9.2
driver.hpp
Go to the documentation of this file.
1
22#ifndef LELY_COCPP_DRIVER_HPP_
23#define LELY_COCPP_DRIVER_HPP_
24
25#include <lely/aio/loop.hpp>
26#include <lely/coapp/master.hpp>
27
28namespace lely {
29
30namespace canopen {
31
34 public:
35 using CanState = BasicMaster::CanState;
36 using CanError = BasicMaster::CanError;
37
38 using time_point = BasicMaster::time_point;
39
40 DriverBase() = default;
41
42 DriverBase(const DriverBase&) = delete;
43
44 DriverBase& operator=(const DriverBase&) = delete;
45
46 virtual ~DriverBase() = default;
47
52 virtual aio::ExecutorBase GetExecutor() const noexcept = 0;
53
55 virtual uint8_t netid() const noexcept = 0;
56
58 virtual uint8_t id() const noexcept = 0;
59
65 virtual void OnCanState(CanState new_state, CanState old_state) noexcept = 0;
66
72 virtual void OnCanError(CanError error) noexcept = 0;
73
81 virtual void OnCommand(NmtCommand cs) noexcept = 0;
82
96 virtual void OnNodeGuarding(bool occurred) noexcept = 0;
97
111 virtual void OnHeartbeat(bool occurred) noexcept = 0;
112
123 virtual void OnState(NmtState st) noexcept = 0;
124
165 virtual void OnBoot(NmtState st, char es,
166 const ::std::string& what) noexcept = 0;
167
183 virtual void OnConfig(
184 ::std::function<void(::std::error_code ec)> res) noexcept = 0;
185
209 virtual void OnRpdo(int num, ::std::error_code ec, const void* p,
210 ::std::size_t n) noexcept = 0;
211
225 virtual void OnRpdoError(int num, uint16_t eec, uint8_t er) noexcept = 0;
226
249 virtual void OnTpdo(int num, ::std::error_code ec, const void* p,
250 ::std::size_t n) noexcept = 0;
251
262 virtual void OnSync(uint8_t cnt, const Node::time_point& t) noexcept = 0;
263
273 virtual void OnSyncError(uint16_t eec, uint8_t er) noexcept = 0;
274
282 virtual void OnTime(
283 const ::std::chrono::system_clock::time_point& abs_time) noexcept = 0;
284
294 virtual void OnEmcy(uint16_t eec, uint8_t er, uint8_t msef[5]) noexcept = 0;
295};
296
298class BasicDriver : private DriverBase {
299 friend class BasicMaster;
300
301 public:
302 using DriverBase::time_point;
303
317 BasicDriver(aio::LoopBase& loop, aio::ExecutorBase& exec, BasicMaster& master,
318 uint8_t id);
319
320 virtual ~BasicDriver();
321
323 aio::LoopBase
324 GetLoop() const noexcept {
325 return loop_;
326 }
327
328 aio::ExecutorBase
329 GetExecutor() const noexcept final override {
330 return exec_;
331 }
332
333 uint8_t netid() const noexcept final override;
334
335 uint8_t
336 id() const noexcept final override {
337 return id_;
338 }
339
346 void
348 master.Error(id());
349 }
350
356 template <class T, class F>
357 void
358 SubmitRead(uint16_t idx, uint8_t subidx, F&& con) {
359 auto exec = GetExecutor();
360 master.SubmitRead<T>(id(), idx, subidx, exec, ::std::forward<F>(con));
361 }
362
369 template <class T, class F>
370 void
371 SubmitRead(uint16_t idx, uint8_t subidx, F&& con, ::std::error_code& ec) {
372 auto exec = GetExecutor();
373 master.SubmitRead<T>(id(), idx, subidx, exec, ::std::forward<F>(con), ec);
374 }
375
382 template <class T, class F>
383 void
384 SubmitRead(uint16_t idx, uint8_t subidx, F&& con,
385 const Sdo::duration& timeout) {
386 auto exec = GetExecutor();
387 master.SubmitRead<T>(id(), idx, subidx, exec, ::std::forward<F>(con),
388 timeout);
389 }
390
406 template <class T, class F>
407 void
408 SubmitRead(uint16_t idx, uint8_t subidx, F&& con,
409 const Sdo::duration& timeout, ::std::error_code& ec) {
410 auto exec = GetExecutor();
411 master.SubmitRead<T>(id(), idx, subidx, exec, ::std::forward<F>(con),
412 timeout, ec);
413 }
414
421 template <class T, class F>
422 void
423 SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con) {
424 auto exec = GetExecutor();
425 master.SubmitWrite<T>(id(), idx, subidx, ::std::forward<T>(value), exec,
426 ::std::forward<F>(con));
427 }
428
435 template <class T, class F>
436 void
437 SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con,
438 ::std::error_code& ec) {
439 auto exec = GetExecutor();
440 master.SubmitWrite<T>(id(), idx, subidx, ::std::forward<T>(value), exec,
441 ::std::forward<F>(con), ec);
442 }
443
450 template <class T, class F>
451 void
452 SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con,
453 const Sdo::duration& timeout) {
454 auto exec = GetExecutor();
455 master.SubmitWrite<T>(id(), idx, subidx, ::std::forward<T>(value), exec,
456 ::std::forward<F>(con), timeout);
457 }
458
475 template <class T, class F>
476 void
477 SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con,
478 const Sdo::duration& timeout, ::std::error_code& ec) {
479 auto exec = GetExecutor();
480 master.SubmitWrite<T>(id(), idx, subidx, ::std::forward<T>(value), exec,
481 ::std::forward<F>(con), timeout, ec);
482 }
483
490 template <class T>
491 aio::Future<::std::tuple<::std::error_code, T>>
492 AsyncRead(uint16_t idx, uint8_t subidx) {
493 auto loop = GetLoop();
494 auto exec = GetExecutor();
495 return master.AsyncRead<T>(loop, exec, id(), idx, subidx);
496 }
497
512 template <class T>
513 aio::Future<::std::tuple<::std::error_code, T>>
514 AsyncRead(uint16_t idx, uint8_t subidx, const Sdo::duration& timeout) {
515 auto loop = GetLoop();
516 auto exec = GetExecutor();
517 return master.AsyncRead<T>(loop, exec, id(), idx, subidx, timeout);
518 }
519
526 template <class T>
527 aio::Future<::std::error_code>
528 AsyncWrite(uint16_t idx, uint8_t subidx, T&& value) {
529 auto loop = GetLoop();
530 auto exec = GetExecutor();
531 return master.AsyncWrite(loop, exec, id(), idx, subidx,
532 ::std::forward<T>(value));
533 }
534
549 template <class T>
550 aio::Future<::std::error_code>
551 AsyncWrite(uint16_t idx, uint8_t subidx, T&& value,
552 const Sdo::duration& timeout) {
553 auto loop = GetLoop();
554 auto exec = GetExecutor();
555 return master.AsyncWrite(loop, exec, id(), idx, subidx,
556 ::std::forward<T>(value), timeout);
557 }
558
564 template <class T>
565 T
566 RunRead(uint16_t idx, uint8_t subidx) {
567 ::std::error_code ec;
568 auto r = RunRead<T>(idx, subidx, ec);
569 if (ec) throw SdoError(netid(), id(), idx, subidx, ec, "RunRead");
570 return r;
571 }
572
579 template <class T>
580 T
581 RunRead(uint16_t idx, uint8_t subidx, ::std::error_code& ec) {
582 T value{};
583 auto future = AsyncRead<T>(idx, subidx);
584 if (future) {
585 auto t = future.Get();
586 ec = ::std::get<0>(t);
587 value = ::std::move(::std::get<1>(t));
588 } else {
589 ec = SdoErrc::NO_SDO;
590 }
591 return value;
592 }
593
600 template <class T>
601 T
602 RunRead(uint16_t idx, uint8_t subidx, const Sdo::duration& timeout) {
603 ::std::error_code ec;
604 auto r = RunRead<T>(idx, subidx, timeout, ec);
605 if (ec) throw SdoError(netid(), id(), idx, subidx, ec, "RunRead");
606 return r;
607 }
608
624 template <class T>
625 T
626 RunRead(uint16_t idx, uint8_t subidx, const Sdo::duration& timeout,
627 ::std::error_code& ec) {
628 T value{};
629 auto future = AsyncRead<T>(idx, subidx, timeout);
630 if (future) {
631 auto t = future.Get();
632 ec = ::std::get<0>(t);
633 value = ::std::move(::std::get<1>(t));
634 } else {
635 ec = SdoErrc::NO_SDO;
636 }
637 return value;
638 }
639
645 template <class T>
646 void
647 RunWrite(uint16_t idx, uint8_t subidx, T&& value) {
648 ::std::error_code ec;
649 RunWrite(idx, subidx, ::std::forward<T>(value), ec);
650 if (ec) throw SdoError(netid(), id(), idx, subidx, ec, "RunWrite");
651 }
652
659 template <class T>
660 void
661 RunWrite(uint16_t idx, uint8_t subidx, T&& value, ::std::error_code& ec) {
662 auto future = AsyncWrite(idx, subidx, ::std::forward<T>(value));
663 ec = future ? future.Get() : SdoErrc::NO_SDO;
664 }
665
672 template <class T>
673 void
674 RunWrite(uint16_t idx, uint8_t subidx, T&& value,
675 const Sdo::duration& timeout) {
676 ::std::error_code ec;
677 RunWrite(idx, subidx, ::std::forward<T>(value), timeout, ec);
678 if (ec) throw SdoError(netid(), id(), idx, subidx, ec, "RunWrite");
679 }
680
695 template <class T>
696 void
697 RunWrite(uint16_t idx, uint8_t subidx, T&& value,
698 const Sdo::duration& timeout, ::std::error_code& ec) {
699 auto future = AsyncWrite(idx, subidx, ::std::forward<T>(value), timeout);
700 ec = future ? future.Get() : SdoErrc::NO_SDO;
701 }
702
705
712 template <class F>
713 void
714 Post(F&& f) {
715 auto* op = new aio::TaskWrapper([=](::std::error_code ec) {
716 if (!ec) f();
717 });
718 GetExecutor().Post(*op);
719 }
720
721 private:
722 void
723 OnCanState(CanState /*new_state*/, CanState /*old_state*/) noexcept override {
724 }
725
726 void
727 OnCanError(CanError /*error*/) noexcept override {}
728
729 void
730 OnCommand(NmtCommand /*cs*/) noexcept override {}
731
732 void
733 OnNodeGuarding(bool /*occurred*/) noexcept override {}
734
735 void
736 OnHeartbeat(bool /*occurred*/) noexcept override {}
737
738 void
739 OnState(NmtState /*st*/) noexcept override {}
740
741 void
742 OnBoot(NmtState /*st*/, char /*es*/,
743 const ::std::string& /*what*/) noexcept override {}
744
745 void
746 OnConfig(::std::function<void(::std::error_code ec)> res) noexcept override {
747 res(::std::error_code());
748 }
749
750 void
751 OnRpdo(int /*num*/, ::std::error_code /*ec*/, const void* /*p*/,
752 ::std::size_t /*n*/) noexcept override {}
753
754 void
755 OnRpdoError(int /*num*/, uint16_t /*eec*/, uint8_t /*er*/) noexcept override {
756 }
757
758 void
759 OnTpdo(int /*num*/, ::std::error_code /*ec*/, const void* /*p*/,
760 ::std::size_t /*n*/) noexcept override {}
761
762 void
763 OnSync(uint8_t /*cnt*/, const time_point& /*t*/) noexcept override {}
764
765 void
766 OnSyncError(uint16_t /*eec*/, uint8_t /*er*/) noexcept override {}
767
768 void
769 OnTime(const ::std::chrono::system_clock::
770 time_point& /*abs_time*/) noexcept override {}
771
772 void
773 OnEmcy(uint16_t /*eec*/, uint8_t /*er*/,
774 uint8_t /*msef*/[5]) noexcept override {}
775
776 aio_loop_t* loop_{nullptr};
777 aio_exec_t* exec_{nullptr};
778 uint8_t id_{0xff};
779};
780
781namespace detail {
782
788 protected:
789 aio::Loop loop{};
790 aio::Executor exec{loop};
791};
792
793} // namespace detail
794
797 public:
798 LoopDriver(BasicMaster& master, uint8_t id);
799 ~LoopDriver();
800
801 private:
802 struct Impl_;
803 ::std::unique_ptr<Impl_> impl_;
804};
805
806} // namespace canopen
807
808} // namespace lely
809
810#endif // LELY_COCPP_DRIVER_HPP_
The base class for drivers for remote CANopen nodes.
Definition: driver.hpp:298
void RunWrite(uint16_t idx, uint8_t subidx, T &&value)
Equivalent to RunWrite(uint16_t idx, uint8_t subidx, T&& value, ::std::error_code& ec),...
Definition: driver.hpp:647
void SubmitWrite(uint16_t idx, uint8_t subidx, T &&value, F &&con)
Equivalent to SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con, ::std::error_code& ec),...
Definition: driver.hpp:423
aio::Future<::std::error_code > AsyncWrite(uint16_t idx, uint8_t subidx, T &&value, const Sdo::duration &timeout)
Queues an asynchronous write (SDO download) operation and returns a future.
Definition: driver.hpp:551
T RunRead(uint16_t idx, uint8_t subidx, const Sdo::duration &timeout, ::std::error_code &ec)
Queues an asynchronous read (SDO upload) operation and runs the event loop until the operation is com...
Definition: driver.hpp:626
aio::Future<::std::tuple<::std::error_code, T > > AsyncRead(uint16_t idx, uint8_t subidx, const Sdo::duration &timeout)
Queues an asynchronous read (SDO upload) operation and returns a future.
Definition: driver.hpp:514
T RunRead(uint16_t idx, uint8_t subidx)
Equivalent to RunRead(uint16_t idx, uint8_t subidx, ::std::error_code& ec), except that it throws lel...
Definition: driver.hpp:566
void SubmitWrite(uint16_t idx, uint8_t subidx, T &&value, F &&con, const Sdo::duration &timeout)
Equivalent to SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con, const Sdo::duration& time...
Definition: driver.hpp:452
T RunRead(uint16_t idx, uint8_t subidx, const Sdo::duration &timeout)
Equivalent to RunRead(uint16_t idx, uint8_t subidx, const Sdo::duration& timeout, ::std::error_code& ...
Definition: driver.hpp:602
aio::Future<::std::tuple<::std::error_code, T > > AsyncRead(uint16_t idx, uint8_t subidx)
Equivalent to AsyncRead(uint16_t idx, uint8_t subidx, const Sdo::duration& timeout),...
Definition: driver.hpp:492
aio::Future<::std::error_code > AsyncWrite(uint16_t idx, uint8_t subidx, T &&value)
Equivalent to AsyncWrite(uint16_t idx, uint8_t subidx, T&& value, const Sdo::duration& timeout),...
Definition: driver.hpp:528
void RunWrite(uint16_t idx, uint8_t subidx, T &&value, const Sdo::duration &timeout, ::std::error_code &ec)
Queues an asynchronous write (SDO download) operation and runs the event loop until the operation is ...
Definition: driver.hpp:697
T RunRead(uint16_t idx, uint8_t subidx, ::std::error_code &ec)
Equivalent to RunRead(uint16_t idx, uint8_t subidx, const Sdo::duration& timeout, ::std::error_code& ...
Definition: driver.hpp:581
void Post(F &&f)
Schedules the specified Callable object for execution by the executor for this driver.
Definition: driver.hpp:714
void RunWrite(uint16_t idx, uint8_t subidx, T &&value, const Sdo::duration &timeout)
Equivalent to RunWrite(uint16_t idx, uint8_t subidx, T&& value, const Sdo::duration& timeout,...
Definition: driver.hpp:674
void SubmitRead(uint16_t idx, uint8_t subidx, F &&con, ::std::error_code &ec)
Equivalent to SubmitRead(uint16_t idx, uint8_t subidx, F&& con, const Sdo::duration& timeout,...
Definition: driver.hpp:371
void SubmitWrite(uint16_t idx, uint8_t subidx, T &&value, F &&con, ::std::error_code &ec)
Equivalent to SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con, const Sdo::duration& time...
Definition: driver.hpp:437
void SubmitRead(uint16_t idx, uint8_t subidx, F &&con, const Sdo::duration &timeout, ::std::error_code &ec)
Queues an asynchronous read (SDO upload) operation.
Definition: driver.hpp:408
void SubmitWrite(uint16_t idx, uint8_t subidx, T &&value, F &&con, const Sdo::duration &timeout, ::std::error_code &ec)
Queues an asynchronous write (SDO download) operation.
Definition: driver.hpp:477
void SubmitRead(uint16_t idx, uint8_t subidx, F &&con)
Equivalent to SubmitRead(uint16_t idx, uint8_t subidx, F&& con, ::std::error_code& ec),...
Definition: driver.hpp:358
aio::ExecutorBase GetExecutor() const noexcept final override
Returns the executor used to execute event handlers for this driver, including SDO confirmation funct...
Definition: driver.hpp:329
void Error()
Indicates the occurrence of an error event on the remote node and triggers the error handling process...
Definition: driver.hpp:347
void RunWrite(uint16_t idx, uint8_t subidx, T &&value, ::std::error_code &ec)
Equivalent to RunWrite(uint16_t idx, uint8_t subidx, T&& value, const Sdo::duration& timeout,...
Definition: driver.hpp:661
aio::LoopBase GetLoop() const noexcept
Returns the event loop used to create promises and futures.
Definition: driver.hpp:324
void SubmitRead(uint16_t idx, uint8_t subidx, F &&con, const Sdo::duration &timeout)
Equivalent to SubmitRead(uint16_t idx, uint8_t subidx, F&& con, const Sdo::duration& timeout,...
Definition: driver.hpp:384
BasicMaster & master
A reference to the master with which this driver is registered.
Definition: driver.hpp:704
The CANopen master.
Definition: master.hpp:46
void SubmitRead(uint8_t id, Sdo::UploadRequest< T > &req)
Equivalent to SubmitRead(uint8_t id, Sdo::UploadRequest<T>& req, ::std::error_code& ec),...
Definition: master.hpp:481
aio::Future<::std::error_code > AsyncWrite(aio::LoopBase &loop, aio::ExecutorBase &exec, uint8_t id, uint16_t idx, uint8_t subidx, T &&value)
Equivalent to AsyncWrite(aio::LoopBase& loop, aio::ExecutorBase& exec, uint8_t id,...
Definition: master.hpp:775
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
aio::Future<::std::tuple<::std::error_code, T > > AsyncRead(aio::LoopBase &loop, aio::ExecutorBase &exec, uint8_t id, uint16_t idx, uint8_t subidx)
Equivalent to AsyncRead(aio::LoopBase& loop, aio::ExecutorBase& exec, uint8_t id, uint16_t idx,...
Definition: master.hpp:729
void SubmitWrite(uint8_t id, Sdo::DownloadRequest< T > &req)
Equivalent to SubmitWrite(uint8_t id, Sdo::DownloadRequest<T>& req, ::std::error_code& ec),...
Definition: master.hpp:601
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 uint8_t netid() const noexcept=0
Returns the network-ID.
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.
A CANopen driver running its own dedicated event loop in a separate thread.
Definition: driver.hpp:796
The base class for CANopen nodes.
Definition: node.hpp:109
The type of exception thrown when an SDO abort code is received.
Definition: sdo_error.hpp:116
::std::chrono::milliseconds duration
The type used to represent an SDO timeout duration.
Definition: sdo.hpp:51
A base class for lely::canopen::LoopDriver, containing an event loop and the associated executor.
Definition: driver.hpp:787
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 CANopen master decla...
NmtState
The NMT states.
Definition: node.hpp:50
@ NO_SDO
Resource not available: SDO connection.
NmtCommand
The NMT command specifiers.
Definition: node.hpp:36
Global namespace for the Lely Industries N.V. libraries.
Definition: buf.hpp:32
STL namespace.
The internal implementation of lely::canopen::LoopDriver.
Definition: driver.cpp:40