Lely core libraries  2.2.5
driver.hpp
Go to the documentation of this file.
1 
22 #ifndef LELY_COAPP_DRIVER_HPP_
23 #define LELY_COAPP_DRIVER_HPP_
24 
25 #include <lely/coapp/master.hpp>
26 
27 #include <map>
28 #include <string>
29 #include <utility>
30 
31 namespace lely {
32 
33 namespace canopen {
34 
36 class DriverBase {
37  public:
38  using time_point = BasicMaster::time_point;
39 
40  DriverBase() = default;
41 
42  DriverBase(const DriverBase&) = delete;
43  DriverBase& operator=(const DriverBase&) = delete;
44 
45  virtual ~DriverBase() = default;
46 
51  virtual ev::Executor GetExecutor() const noexcept = 0;
52 
54  virtual uint8_t netid() const noexcept = 0;
55 
57  virtual uint8_t id() const noexcept = 0;
58 
64  virtual void OnCanState(io::CanState new_state,
65  io::CanState old_state) noexcept = 0;
66 
72  virtual void OnCanError(io::CanError error) noexcept = 0;
73 
74  /*
75  * The function invoked when a value is successfully written to an RPDO-mapped
76  * object in the local object dictionary by a Receive-PDO (or SDO download)
77  * request.
78  *
79  * @param idx the remote object index.
80  * @param subidx the remote object sub-index.
81  */
82  virtual void OnRpdoWrite(uint16_t idx, uint8_t subidx) noexcept = 0;
83 
91  virtual void OnCommand(NmtCommand cs) noexcept = 0;
92 
106  virtual void OnNodeGuarding(bool occurred) noexcept = 0;
107 
121  virtual void OnHeartbeat(bool occurred) noexcept = 0;
122 
133  virtual void OnState(NmtState st) noexcept = 0;
134 
175  virtual void OnBoot(NmtState st, char es,
176  const ::std::string& what) noexcept = 0;
177 
193  virtual void OnConfig(
194  ::std::function<void(::std::error_code ec)> res) noexcept = 0;
195 
209  virtual void OnDeconfig(
210  ::std::function<void(::std::error_code ec)> res) noexcept = 0;
211 
222  virtual void OnSync(uint8_t cnt, const time_point& t) noexcept = 0;
223 
233  virtual void OnSyncError(uint16_t eec, uint8_t er) noexcept = 0;
234 
242  virtual void OnTime(
243  const ::std::chrono::system_clock::time_point& abs_time) noexcept = 0;
244 
254  virtual void OnEmcy(uint16_t eec, uint8_t er, uint8_t msef[5]) noexcept = 0;
255 };
256 
259  public:
261  virtual int Number() const noexcept = 0;
262 
268  virtual SdoFuture<void> AsyncConfig() = 0;
269 
274  virtual SdoFuture<void> AsyncDeconfig() = 0;
275 };
276 
279  protected ::std::map<uint8_t, LogicalDriverBase*> {
280  friend class LoopDriver;
281 
282  public:
283  using DriverBase::time_point;
284  using duration = BasicMaster::duration;
286 
299  explicit BasicDriver(ev_exec_t* exec, BasicMaster& master, uint8_t id);
300 
305  explicit BasicDriver(BasicMaster& master, uint8_t id)
306  : BasicDriver(nullptr, master, id) {}
307 
308  virtual ~BasicDriver();
309 
311  GetExecutor() const noexcept final {
312  return ev::Executor(exec_);
313  }
314 
315  uint8_t
316  netid() const noexcept final {
317  return master.netid();
318  }
319 
320  uint8_t
321  id() const noexcept final {
322  return id_;
323  }
324 
333  void
334  ConfigHeartbeat(const ::std::chrono::milliseconds& ms,
335  ::std::error_code& ec) {
336  master.ConfigHeartbeat(id(), ms, ec);
337  }
338 
348  void
349  ConfigHeartbeat(const ::std::chrono::milliseconds& ms) {
350  master.ConfigHeartbeat(id(), ms);
351  }
352 
359  bool
360  Boot() {
361  return master.Boot(id());
362  }
363 
373  bool
374  IsReady() const {
375  return master.IsReady(id());
376  }
377 
384  void
385  Error() {
386  master.Error(id());
387  }
388 
396  template <class F>
397  void
398  SubmitWait(const time_point& t, F&& f) {
399  return master.SubmitWait(t, GetExecutor(), ::std::forward<F>(f));
400  }
401 
409  template <class F>
410  void
411  SubmitWait(const duration& d, F&& f) {
412  return master.SubmitWait(d, GetExecutor(), ::std::forward<F>(f));
413  }
414 
424  AsyncWait(const time_point& t) {
425  return master.AsyncWait(GetExecutor(), t);
426  }
427 
437  AsyncWait(const duration& d) {
438  return master.AsyncWait(GetExecutor(), d);
439  }
440 
447  template <class T, class F>
448  void
449  SubmitRead(uint16_t idx, uint8_t subidx, F&& con) {
450  master.SubmitRead<T>(GetExecutor(), id(), idx, subidx,
451  ::std::forward<F>(con));
452  }
453 
460  template <class T, class F>
461  void
462  SubmitRead(uint16_t idx, uint8_t subidx, F&& con, ::std::error_code& ec) {
463  master.SubmitRead<T>(GetExecutor(), id(), idx, subidx,
464  ::std::forward<F>(con), ec);
465  }
466 
472  template <class T, class F>
473  void
474  SubmitRead(uint16_t idx, uint8_t subidx, F&& con,
475  const ::std::chrono::milliseconds& timeout) {
476  master.SubmitRead<T>(GetExecutor(), id(), idx, subidx,
477  ::std::forward<F>(con), timeout);
478  }
479 
495  template <class T, class F>
496  void
497  SubmitRead(uint16_t idx, uint8_t subidx, F&& con,
498  const ::std::chrono::milliseconds& timeout,
499  ::std::error_code& ec) {
500  master.SubmitRead<T>(GetExecutor(), id(), idx, subidx,
501  ::std::forward<F>(con), timeout, ec);
502  }
503 
510  template <class T, class F>
511  void
512  SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con) {
513  master.SubmitWrite(GetExecutor(), id(), idx, subidx,
514  ::std::forward<T>(value), ::std::forward<F>(con));
515  }
516 
523  template <class T, class F>
524  void
525  SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con,
526  ::std::error_code& ec) {
527  master.SubmitWrite(GetExecutor(), id(), idx, subidx,
528  ::std::forward<T>(value), ::std::forward<F>(con), ec);
529  }
530 
536  template <class T, class F>
537  void
538  SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con,
539  const ::std::chrono::milliseconds& timeout) {
540  master.SubmitWrite(GetExecutor(), id(), idx, subidx,
541  ::std::forward<T>(value), ::std::forward<F>(con),
542  timeout);
543  }
544 
561  template <class T, class F>
562  void
563  SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con,
564  const ::std::chrono::milliseconds& timeout,
565  ::std::error_code& ec) {
566  master.SubmitWrite(GetExecutor(), id(), idx, subidx,
567  ::std::forward<T>(value), ::std::forward<F>(con),
568  timeout, ec);
569  }
570 
577  template <class T>
579  AsyncRead(uint16_t idx, uint8_t subidx) {
580  return master.AsyncRead<T>(GetExecutor(), id(), idx, subidx);
581  }
582 
597  template <class T>
599  AsyncRead(uint16_t idx, uint8_t subidx,
600  const ::std::chrono::milliseconds& timeout) {
601  return master.AsyncRead<T>(GetExecutor(), id(), idx, subidx, timeout);
602  }
603 
610  template <class T>
612  AsyncWrite(uint16_t idx, uint8_t subidx, T&& value) {
613  return master.AsyncWrite(GetExecutor(), id(), idx, subidx,
614  ::std::forward<T>(value));
615  }
616 
631  template <class T>
633  AsyncWrite(uint16_t idx, uint8_t subidx, T&& value,
634  const ::std::chrono::milliseconds& timeout) {
635  return master.AsyncWrite(GetExecutor(), id(), idx, subidx,
636  ::std::forward<T>(value), timeout);
637  }
638 
649  void Insert(LogicalDriverBase& driver);
650 
656  void Erase(LogicalDriverBase& driver);
657 
664  template <class F, class... Args>
665  void
666  Post(F&& f, Args&&... args) {
667  GetExecutor().post(::std::forward<F>(f), ::std::forward<Args>(args)...);
668  }
669 
672 
679  class BasicMaster::RpdoMapped rpdo_mapped;
680 
687  class BasicMaster::TpdoMapped tpdo_mapped;
688 
691 
692  protected:
693  using MapType = ::std::map<uint8_t, LogicalDriverBase*>;
694 
700  void OnCanState(io::CanState new_state,
701  io::CanState old_state) noexcept override;
702 
708  void OnCanError(io::CanError error) noexcept override;
709 
719  void OnRpdoWrite(uint16_t idx, uint8_t subidx) noexcept override;
720 
726  void OnCommand(NmtCommand cs) noexcept override;
727 
733  void OnNodeGuarding(bool occurred) noexcept override;
734 
740  void OnHeartbeat(bool occurred) noexcept override;
741 
747  void OnState(NmtState st) noexcept override;
748 
754  void OnBoot(NmtState st, char es,
755  const ::std::string& what) noexcept override;
756 
763  void OnConfig(
764  ::std::function<void(::std::error_code ec)> res) noexcept override;
765 
772  void OnDeconfig(
773  ::std::function<void(::std::error_code ec)> res) noexcept override;
774 
780  void OnSync(uint8_t cnt, const time_point& t) noexcept override;
781 
787  void OnSyncError(uint16_t eec, uint8_t er) noexcept override;
788 
794  void OnTime(const ::std::chrono::system_clock::time_point&
795  abs_time) noexcept override;
796 
802  void OnEmcy(uint16_t eec, uint8_t er, uint8_t msef[5]) noexcept override;
803 
810  SdoFuture<void> AsyncConfig(int num = 0);
811 
818  SdoFuture<void> AsyncDeconfig(int num = 0);
819 
820  private:
821  ev_exec_t* exec_{nullptr};
822  const uint8_t id_{0xff};
823 };
824 
825 } // namespace canopen
826 
827 } // namespace lely
828 
829 #endif // LELY_COAPP_DRIVER_HPP_
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 OnSync(uint8_t cnt, const time_point &t) noexcept=0
The function invoked when a SYNC message is sent/received by the master.
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
Definition: ev.h:29
void ConfigHeartbeat(const ::std::chrono::milliseconds &ms)
Configures heartbeat consumption by updating CANopen object 1016 (Consumer heartbeat time)...
Definition: driver.hpp:349
The CANopen master.
Definition: master.hpp:50
SdoFuture< T > AsyncRead(uint16_t idx, uint8_t subidx, const ::std::chrono::milliseconds &timeout)
Queues an asynchronous read (SDO upload) operation and creates a future which becomes ready once the ...
Definition: driver.hpp:599
ev::Executor GetExecutor() const noexcept final
Returns the executor used to execute event handlers for this driver, including SDO confirmation funct...
Definition: driver.hpp:311
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.
void SubmitWrite(uint8_t id, SdoDownloadRequest< T > &req)
Equivalent to SubmitWrite(uint8_t id, SdoDownloadRequest<T>& req, ::std::error_code& ec)...
Definition: master.hpp:843
The base class for drivers for remote CANopen nodes.
Definition: driver.hpp:278
bool IsReady() const
Returns true if the remote node is ready (i.e., the NMT boot slave process has successfully completed...
Definition: driver.hpp:374
void SubmitRead(uint8_t id, SdoUploadRequest< T > &req)
Equivalent to SubmitRead(uint8_t id, SdoUploadRequest<T>& req, ::std::error_code& ec)...
Definition: master.hpp:734
virtual void OnCanState(io::CanState new_state, io::CanState old_state) noexcept=0
The function invoked when a CAN bus state change is detected.
void SubmitWait(const time_point &t, io_tqueue_wait &wait)
Submits a wait operation.
Definition: node.cpp:121
void post(ev_task &task) noexcept
Definition: exec.hpp:75
NmtCommand
The NMT command specifiers.
Definition: node.hpp:42
void Post(F &&f, Args &&... args)
Schedules the specified Callable object for execution by the executor for this driver.
Definition: driver.hpp:666
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 uint8_t netid() const noexcept=0
Returns the network-ID.
virtual uint8_t id() const noexcept=0
Returns the node-ID.
BasicDriver(BasicMaster &master, uint8_t id)
Creates a new driver for a remote CANopen node and registers it with the master.
Definition: driver.hpp:305
The abstract driver interface for a remote CANopen node.
Definition: driver.hpp:36
This header file is part of the C++ CANopen application library; it contains the CANopen master decla...
SdoFuture< void > AsyncWait(const time_point &t)
Submits an asynchronous wait operation and creates a future which becomes ready once the wait operati...
Definition: driver.hpp:424
CanState
The states of a CAN node, depending on the TX/RX error count.
Definition: err.hpp:33
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...
uint8_t id() const noexcept final
Returns the node-ID.
Definition: driver.hpp:321
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:139
virtual void OnCommand(NmtCommand cs) noexcept=0
The function invoked when an NMT state change occurs on the master.
SdoFuture< T > AsyncRead(uint16_t idx, uint8_t subidx)
Equivalent to AsyncRead(uint16_t idx, uint8_t subidx, const ::std::chrono::milliseconds& timeout)...
Definition: driver.hpp:579
void SubmitRead(uint16_t idx, uint8_t subidx, F &&con, const ::std::chrono::milliseconds &timeout)
Equivalent to SubmitRead(uint16_t idx, uint8_t subidx, F&& con, const ::std::chrono::milliseconds& ti...
Definition: driver.hpp:474
uint8_t netid() const noexcept
Returns the network-ID.
Definition: device.cpp:154
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 ::std::chrono::milliseconds& ti...
Definition: driver.hpp:462
void SubmitRead(uint16_t idx, uint8_t subidx, F &&con, const ::std::chrono::milliseconds &timeout, ::std::error_code &ec)
Queues an asynchronous read (SDO upload) operation.
Definition: driver.hpp:497
CanError
The error flags of a CAN bus, which are not mutually exclusive.
Definition: err.hpp:47
bool Boot(uint8_t id)
Requests the NMT &#39;boot slave&#39; process for the specified node.
Definition: master.cpp:84
void SubmitRead(uint16_t idx, uint8_t subidx, F &&con)
Equivalent to SubmitRead(uint16_t idx, uint8_t subidx, F&& con, const ::std::chrono::milliseconds& ti...
Definition: driver.hpp:449
A CANopen driver running its own dedicated event loop in a separate thread.
Definition: loop_driver.hpp:51
SdoFuture< T > AsyncRead(ev_exec_t *exec, uint8_t id, uint16_t idx, uint8_t subidx)
Equivalent to AsyncRead(ev_exec_t* exec, uint8_t id, uint16_t idx, uint8_t subidx, const ::std::chrono::milliseconds& timeout), except that it uses the SDO timeout given by GetTimeout().
Definition: master.hpp:956
A mutator providing read/write access to TPDO-mapped objects in a remote object dictionary.
Definition: master.hpp:467
void SubmitWait(const time_point &t, F &&f)
Submits a wait operation.
Definition: driver.hpp:398
void SubmitWait(const duration &d, F &&f)
Submits a wait operation.
Definition: driver.hpp:411
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...
The type of objects thrown as exceptions to report a system error with an associated error code...
Definition: exception.hpp:54
An accessor providing read-only access to TPDO-mapped objects in a remote object dictionary.
Definition: master.hpp:437
void SubmitWrite(uint16_t idx, uint8_t subidx, T &&value, F &&con, const ::std::chrono::milliseconds &timeout, ::std::error_code &ec)
Queues an asynchronous write (SDO download) operation.
Definition: driver.hpp:563
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.
void SubmitWrite(uint16_t idx, uint8_t subidx, T &&value, F &&con, const ::std::chrono::milliseconds &timeout)
Equivalent to SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con, const ::std::chrono::mill...
Definition: driver.hpp:538
void ConfigHeartbeat(uint8_t id, const ::std::chrono::milliseconds &ms, ::std::error_code &ec)
Configures heartbeat consumption for the specified node by updating CANopen object 1016 (Consumer hea...
Definition: node.cpp:217
SdoFuture< void > AsyncWait(const duration &d)
Submits an asynchronous wait operation and creates a future which becomes ready once the wait operati...
Definition: driver.hpp:437
virtual void OnHeartbeat(bool occurred) noexcept=0
The function invoked when a heartbeat timeout event occurs or is resolved for the remote node...
SdoFuture< void > AsyncWrite(ev_exec_t *exec, uint8_t id, uint16_t idx, uint8_t subidx, T &&value)
Equivalent to AsyncWrite(ev_exec_t* exec, uint8_t id, uint16_t idx, uint8_t subidx, T&& value, const ::std::chrono::milliseconds& timeout), except that it uses the SDO timeout given by GetTimeout().
Definition: master.hpp:1001
An abstract task executor. This class is a wrapper around ev_exec_t*.
Definition: exec.hpp:38
BasicMaster & master
A reference to the master with which this driver is registered.
Definition: driver.hpp:671
bool Boot()
Requests the NMT &#39;boot slave&#39; process for the remote node.
Definition: driver.hpp:360
SdoFuture< void > AsyncWrite(uint16_t idx, uint8_t subidx, T &&value)
Equivalent to AsyncWrite(uint16_t idx, uint8_t subidx, T&& value, const ::std::chrono::milliseconds& ...
Definition: driver.hpp:612
void Error()
Indicates the occurrence of an error event on the remote node and triggers the error handling process...
Definition: driver.hpp:385
virtual ev::Executor GetExecutor() const noexcept=0
Returns the executor used to execute event handlers for this driver, including SDO confirmation funct...
uint8_t netid() const noexcept final
Returns the network-ID.
Definition: driver.hpp:316
NmtState
The NMT states.
Definition: node.hpp:56
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 ::std::chrono::mill...
Definition: driver.hpp:525
virtual void OnCanError(io::CanError error) noexcept=0
The function invoked when an error is detected on the CAN bus.
ev::Future< void, ::std::exception_ptr > AsyncWait(ev_exec_t *exec, const time_point &t, io_tqueue_wait **pwait=nullptr)
Submits an asynchronous wait operation and creates a future which becomes ready once the wait operati...
Definition: node.cpp:132
void ConfigHeartbeat(const ::std::chrono::milliseconds &ms, ::std::error_code &ec)
Configures heartbeat consumption by updating CANopen object 1016 (Consumer heartbeat time)...
Definition: driver.hpp:334
Definition: buf.hpp:32
SdoFuture< void > AsyncWrite(uint16_t idx, uint8_t subidx, T &&value, const ::std::chrono::milliseconds &timeout)
Queues an asynchronous write (SDO download) operation and creates a future which becomes ready once t...
Definition: driver.hpp:633
virtual void OnDeconfig(::std::function< void(::std::error_code ec)> res) noexcept=0
The function invoked by BasicMaster::AsyncDeconfig() to start the deconfiguration process...
The abstract driver interface for a logical device on a remote CANopen node.
Definition: driver.hpp:258
TpdoEventMutex & tpdo_event_mutex
Definition: driver.hpp:690
bool IsReady(uint8_t id) const
Returns true if the remote node is ready (i.e., the NMT &#39;boot slave&#39; process has successfully complet...
Definition: master.cpp:106
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, const ::std::chrono::mill...
Definition: driver.hpp:512
A future.
Definition: future.hpp:50