Lely core libraries  2.3.4
logical_driver.hpp
Go to the documentation of this file.
1 
22 #ifndef LELY_COAPP_LOGICAL_DRIVER_HPP_
23 #define LELY_COAPP_LOGICAL_DRIVER_HPP_
24 
25 #include <lely/coapp/driver.hpp>
26 
27 #include <string>
28 #include <utility>
29 
30 namespace lely {
31 
32 namespace canopen {
33 
34 template <class = BasicDriver>
35 class BasicLogicalDriver;
36 
38 template <>
40  public:
41  using DriverBase::time_point;
42  using duration = BasicMaster::duration;
44 
45  BasicLogicalDriver(BasicDriver& driver, int num = 1, uint32_t dev = 0);
46 
47  virtual ~BasicLogicalDriver();
48 
50  GetExecutor() const noexcept final {
51  return driver.GetExecutor();
52  }
53 
54  uint8_t
55  netid() const noexcept final {
56  return driver.netid();
57  }
58 
59  uint8_t
60  id() const noexcept final {
61  return driver.id();
62  }
63 
64  int
65  Number() const noexcept final {
66  return num_;
67  }
68 
70  uint32_t
71  DeviceType() const noexcept {
72  return dev_;
73  }
74 
79  int
80  Profile() const noexcept {
81  return DeviceType() & 0xffff;
82  }
83 
91  bool
92  IsReady() const {
93  return driver.IsReady();
94  }
95 
102  void
103  Error() {
104  driver.Error();
105  }
106 
114  template <class F>
115  void
116  SubmitWait(const time_point& t, F&& f) {
117  return driver.SubmitWait(t, ::std::forward<F>(f));
118  }
119 
127  template <class F>
128  void
129  SubmitWait(const duration& d, F&& f) {
130  return driver.SubmitWait(d, ::std::forward<F>(f));
131  }
132 
142  AsyncWait(const time_point& t) {
143  return driver.AsyncWait(t);
144  }
145 
155  AsyncWait(const duration& d) {
156  return driver.AsyncWait(d);
157  }
158 
165  template <class T, class F>
166  void
167  SubmitRead(uint16_t idx, uint8_t subidx, F&& con) {
168  driver.SubmitRead<T>(ObjectIndex(idx), subidx, ::std::forward<F>(con));
169  }
170 
177  template <class T, class F>
178  void
179  SubmitRead(uint16_t idx, uint8_t subidx, F&& con, ::std::error_code& ec) {
180  driver.SubmitRead<T>(ObjectIndex(idx), subidx, ::std::forward<F>(con), ec);
181  }
182 
188  template <class T, class F>
189  void
190  SubmitRead(uint16_t idx, uint8_t subidx, F&& con,
191  const ::std::chrono::milliseconds& timeout) {
192  driver.SubmitRead<T>(ObjectIndex(idx), subidx, ::std::forward<F>(con),
193  timeout);
194  }
195 
211  template <class T, class F>
212  void
213  SubmitRead(uint16_t idx, uint8_t subidx, F&& con,
214  const ::std::chrono::milliseconds& timeout,
215  ::std::error_code& ec) {
216  driver.SubmitRead<T>(ObjectIndex(idx), subidx, ::std::forward<F>(con),
217  timeout, ec);
218  }
219 
226  template <class T, class F>
227  void
228  SubmitBlockRead(uint16_t idx, uint8_t subidx, F&& con) {
229  driver.SubmitBlockRead<T>(ObjectIndex(idx), subidx, ::std::forward<F>(con));
230  }
231 
238  template <class T, class F>
239  void
240  SubmitBlockRead(uint16_t idx, uint8_t subidx, F&& con,
241  ::std::error_code& ec) {
242  driver.SubmitBlockRead<T>(ObjectIndex(idx), subidx, ::std::forward<F>(con),
243  ec);
244  }
245 
251  template <class T, class F>
252  void
253  SubmitBlockRead(uint16_t idx, uint8_t subidx, F&& con,
254  const ::std::chrono::milliseconds& timeout) {
255  driver.SubmitBlockRead<T>(ObjectIndex(idx), subidx, ::std::forward<F>(con),
256  timeout);
257  }
258 
278  template <class T, class F>
279  void
280  SubmitBlockRead(uint16_t idx, uint8_t subidx, F&& con,
281  const ::std::chrono::milliseconds& timeout,
282  ::std::error_code& ec) {
283  driver.SubmitBlockRead<T>(ObjectIndex(idx), subidx, ::std::forward<F>(con),
284  timeout, ec);
285  }
286 
293  template <class T, class F>
294  void
295  SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con) {
296  driver.SubmitWrite(ObjectIndex(idx), subidx, ::std::forward<T>(value),
297  ::std::forward<F>(con));
298  }
299 
306  template <class T, class F>
307  void
308  SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con,
309  ::std::error_code& ec) {
310  driver.SubmitWrite(ObjectIndex(idx), subidx, ::std::forward<T>(value),
311  ::std::forward<F>(con), ec);
312  }
313 
319  template <class T, class F>
320  void
321  SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con,
322  const ::std::chrono::milliseconds& timeout) {
323  driver.SubmitWrite(ObjectIndex(idx), subidx, ::std::forward<T>(value),
324  ::std::forward<F>(con), timeout);
325  }
326 
343  template <class T, class F>
344  void
345  SubmitWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con,
346  const ::std::chrono::milliseconds& timeout,
347  ::std::error_code& ec) {
348  driver.SubmitWrite(ObjectIndex(idx), subidx, ::std::forward<T>(value),
349  ::std::forward<F>(con), timeout, ec);
350  }
351 
358  template <class T, class F>
359  void
360  SubmitBlockWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con) {
361  driver.SubmitBlockWrite(ObjectIndex(idx), subidx, ::std::forward<T>(value),
362  ::std::forward<F>(con));
363  }
364 
371  template <class T, class F>
372  void
373  SubmitBlockWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con,
374  ::std::error_code& ec) {
375  driver.SubmitBlockWrite(ObjectIndex(idx), subidx, ::std::forward<T>(value),
376  ::std::forward<F>(con), ec);
377  }
378 
384  template <class T, class F>
385  void
386  SubmitBlockWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con,
387  const ::std::chrono::milliseconds& timeout) {
388  driver.SubmitBlockWrite(ObjectIndex(idx), subidx, ::std::forward<T>(value),
389  ::std::forward<F>(con), timeout);
390  }
391 
412  template <class T, class F>
413  void
414  SubmitBlockWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con,
415  const ::std::chrono::milliseconds& timeout,
416  ::std::error_code& ec) {
417  driver.SubmitBlockWrite(ObjectIndex(idx), subidx, ::std::forward<T>(value),
418  ::std::forward<F>(con), timeout, ec);
419  }
420 
427  template <class T>
429  AsyncRead(uint16_t idx, uint8_t subidx) {
430  return driver.AsyncRead<T>(ObjectIndex(idx), subidx);
431  }
432 
447  template <class T>
449  AsyncRead(uint16_t idx, uint8_t subidx,
450  const ::std::chrono::milliseconds& timeout) {
451  return driver.AsyncRead<T>(ObjectIndex(idx), subidx, timeout);
452  }
453 
460  template <class T>
462  AsyncBlockRead(uint16_t idx, uint8_t subidx) {
463  return driver.AsyncBlockRead<T>(ObjectIndex(idx), subidx);
464  }
465 
484  template <class T>
486  AsyncBlockRead(uint16_t idx, uint8_t subidx,
487  const ::std::chrono::milliseconds& timeout) {
488  return driver.AsyncBlockRead<T>(ObjectIndex(idx), subidx, timeout);
489  }
490 
497  template <class T>
499  AsyncWrite(uint16_t idx, uint8_t subidx, T&& value) {
500  return driver.AsyncWrite(ObjectIndex(idx), subidx,
501  ::std::forward<T>(value));
502  }
503 
518  template <class T>
520  AsyncWrite(uint16_t idx, uint8_t subidx, T&& value,
521  const ::std::chrono::milliseconds& timeout) {
522  return driver.AsyncWrite(ObjectIndex(idx), subidx, ::std::forward<T>(value),
523  timeout);
524  }
525 
532  template <class T>
534  AsyncBlockWrite(uint16_t idx, uint8_t subidx, T&& value) {
535  return driver.AsyncBlockWrite(ObjectIndex(idx), subidx,
536  ::std::forward<T>(value));
537  }
538 
557  template <class T>
559  AsyncBlockWrite(uint16_t idx, uint8_t subidx, T&& value,
560  const ::std::chrono::milliseconds& timeout) {
561  return driver.AsyncBlockWrite(ObjectIndex(idx), subidx,
562  ::std::forward<T>(value), timeout);
563  }
564 
571  template <class F, class... Args>
572  void
573  Post(F&& f, Args&&... args) {
574  GetExecutor().post(::std::forward<F>(f), ::std::forward<Args>(args)...);
575  }
576 
579 
585 
586  class RpdoMapped {
587  friend class BasicLogicalDriver;
588 
589  public:
591  operator[](uint16_t idx) const {
592  return self_.driver.rpdo_mapped[self_.ObjectIndex(idx)];
593  }
594 
595  private:
596  explicit RpdoMapped(BasicLogicalDriver& self) noexcept : self_(self) {}
597 
598  BasicLogicalDriver& self_;
599  } rpdo_mapped;
600 
601  class TpdoMapped {
602  friend class BasicLogicalDriver;
603 
604  public:
606  operator[](uint16_t idx) {
607  return self_.driver.tpdo_mapped[self_.ObjectIndex(idx)];
608  }
609 
611  operator[](uint16_t idx) const {
612  const auto& tpdo_mapped = self_.driver.tpdo_mapped;
613  return tpdo_mapped[self_.ObjectIndex(idx)];
614  }
615 
616  private:
617  explicit TpdoMapped(BasicLogicalDriver& self) noexcept : self_(self) {}
618 
619  BasicLogicalDriver& self_;
620  } tpdo_mapped;
621 
624 
625  protected:
626  void
627  OnCanState(io::CanState /*new_state*/,
628  io::CanState /*old_state*/) noexcept override {}
629 
630  void
631  OnCanError(io::CanError /*error*/) noexcept override {}
632 
633  void
634  OnRpdoWrite(uint16_t /*idx*/, uint8_t /*subidx*/) noexcept override {}
635 
636  void
637  OnCommand(NmtCommand /*cs*/) noexcept override {}
638 
639  void
640  // NOLINTNEXTLINE(readability/casting)
641  OnHeartbeat(bool /*occurred*/) noexcept override {}
642 
643  void
644  OnState(NmtState /*st*/) noexcept override {}
645 
646  void
647  OnSync(uint8_t /*cnt*/, const time_point& /*t*/) noexcept override {}
648 
649  void
650  OnSyncError(uint16_t /*eec*/, uint8_t /*er*/) noexcept override {}
651 
652  void
653  OnTime(const ::std::chrono::system_clock::time_point& /*abs_time*/) noexcept
654  override {}
655 
656  void
657  OnEmcy(uint16_t /*eec*/, uint8_t /*er*/,
658  uint8_t /*msef*/[5]) noexcept override {}
659 
660  void
661  // NOLINTNEXTLINE(readability/casting)
662  OnNodeGuarding(bool /*occurred*/) noexcept override {}
663 
664  void
665  OnBoot(NmtState /*st*/, char /*es*/,
666  const ::std::string& /*what*/) noexcept override {}
667 
668  void
669  OnConfig(::std::function<void(::std::error_code ec)> res) noexcept override {
670  res(::std::error_code{});
671  }
672 
673  void
675  ::std::function<void(::std::error_code ec)> res) noexcept override {
676  res(::std::error_code{});
677  }
678 
685  uint16_t
686  ObjectIndex(uint16_t idx) const noexcept {
687  return (idx >= 0x6000 && idx <= 0x67ff) ? idx + (num_ - 1) * 0x800 : idx;
688  }
689 
690  private:
691  SdoFuture<void> AsyncConfig() final;
692  SdoFuture<void> AsyncDeconfig() final;
693 
694  int num_{1};
695  uint32_t dev_{0};
696 };
697 
699 template <class Driver>
700 class BasicLogicalDriver : public BasicLogicalDriver<BasicDriver> {
701  public:
702  BasicLogicalDriver(Driver& driver_, int num = 1, uint32_t dev = 0)
703  : BasicLogicalDriver<BasicDriver>(driver_, num, dev), driver(driver_) {}
704 
709  Driver& driver;
710 };
711 
712 } // namespace canopen
713 
714 } // namespace lely
715 
716 #endif // LELY_COAPP_LOGICAL_DRIVER_HPP_
The base class for drivers for remote CANopen nodes.
Definition: driver.hpp:279
The base class for drivers for logical devices on remote CANopen nodes.
void SubmitWait(const duration &d, F &&f)
Submits a wait operation.
uint8_t netid() const noexcept final
Returns the network-ID.
void Error()
Indicates the occurrence of an error event on the remote node and triggers the error handling process...
void OnConfig(::std::function< void(::std::error_code ec)> res) noexcept override
The function invoked when the 'update configuration' step is reached during the NMT 'boot slave' proc...
uint16_t ObjectIndex(uint16_t idx) const noexcept
Converts an object index, if it is part of the standardized profile area, from the first logical devi...
void OnTime(const ::std::chrono::system_clock::time_point &) noexcept override
The function invoked when a TIME message is received by the master.
void SubmitBlockWrite(uint16_t idx, uint8_t subidx, T &&value, F &&con)
Equivalent to SubmitBlockWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con, const ::std::chrono:...
bool IsReady() const
Returns true if the remote node is ready (i.e., the NMT boot slave process has successfully completed...
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 ...
BasicMaster & master
A reference to the master with which driver is registered.
int Number() const noexcept final
Returns the number of the logical device on the remote node.
uint32_t DeviceType() const noexcept
Returns the device type of the logical device on the remote node.
void OnNodeGuarding(bool) noexcept override
The function invoked when a node guarding timeout event occurs or is resolved 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...
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...
void OnSyncError(uint16_t, uint8_t) noexcept override
The function invoked when the data length of a received SYNC message does not match.
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...
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...
void SubmitWait(const time_point &t, F &&f)
Submits a wait operation.
SdoFuture< T > AsyncRead(uint16_t idx, uint8_t subidx)
Equivalent to AsyncRead(uint16_t idx, uint8_t subidx, const ::std::chrono::milliseconds& timeout),...
uint8_t id() const noexcept final
Returns the node-ID.
void OnCanError(io::CanError) noexcept override
The function invoked when an error is detected on the CAN bus.
void SubmitBlockWrite(uint16_t idx, uint8_t subidx, T &&value, F &&con, const ::std::chrono::milliseconds &timeout, ::std::error_code &ec)
Queues an asynchronous write (SDO block download) operation.
int Profile() const noexcept
Returns the device profile number of the logical device on the remote node, or 0 if the device does n...
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...
void SubmitBlockRead(uint16_t idx, uint8_t subidx, F &&con)
Equivalent to SubmitBlockRead(uint16_t idx, uint8_t subidx, F&& con, const ::std::chrono::millisecond...
void SubmitBlockRead(uint16_t idx, uint8_t subidx, F &&con, const ::std::chrono::milliseconds &timeout)
Equivalent to SubmitBlockRead(uint16_t idx, uint8_t subidx, F&& con, const ::std::chrono::millisecond...
void OnState(NmtState) noexcept override
The function invoked when an NMT state change or boot-up event is detected for the remote node by the...
void SubmitBlockWrite(uint16_t idx, uint8_t subidx, T &&value, F &&con, const ::std::chrono::milliseconds &timeout)
Equivalent to SubmitBlockWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con, const ::std::chrono:...
void Post(F &&f, Args &&... args)
Schedules the specified Callable object for execution by the executor for this driver.
void SubmitBlockRead(uint16_t idx, uint8_t subidx, F &&con, ::std::error_code &ec)
Equivalent to SubmitBlockRead(uint16_t idx, uint8_t subidx, F&& con, const ::std::chrono::millisecond...
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& ...
void OnBoot(NmtState, char, const ::std::string &) noexcept override
The function invoked when the NMT 'boot slave' process completes for the remote node.
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.
SdoFuture< T > AsyncBlockRead(uint16_t idx, uint8_t subidx)
Equivalent to AsyncBlockRead(uint16_t idx, uint8_t subidx, const ::std::chrono::milliseconds& timeout...
void OnCanState(io::CanState, io::CanState) noexcept override
The function invoked when a CAN bus state change is detected.
BasicDriver & driver
A reference to the driver with which this logical device driver is registered.
void OnEmcy(uint16_t, uint8_t, uint8_t[5]) noexcept override
The function invoked when an EMCY message is received from the remote node.
void OnCommand(NmtCommand) noexcept override
The function invoked when an NMT state change occurs on the master.
void SubmitBlockRead(uint16_t idx, uint8_t subidx, F &&con, const ::std::chrono::milliseconds &timeout, ::std::error_code &ec)
Queues an asynchronous read (SDO block upload) operation.
void OnDeconfig(::std::function< void(::std::error_code ec)> res) noexcept override
The function invoked by BasicMaster::AsyncDeconfig() to start the deconfiguration process.
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...
SdoFuture< void > AsyncBlockWrite(uint16_t idx, uint8_t subidx, T &&value, const ::std::chrono::milliseconds &timeout)
Queues an asynchronous write (SDO block download) operation and creates a future which becomes ready ...
void SubmitBlockWrite(uint16_t idx, uint8_t subidx, T &&value, F &&con, ::std::error_code &ec)
Equivalent to SubmitBlockWrite(uint16_t idx, uint8_t subidx, T&& value, F&& con, const ::std::chrono:...
void OnHeartbeat(bool) noexcept override
The function invoked when a heartbeat timeout event occurs or is resolved for the remote node.
SdoFuture< T > AsyncBlockRead(uint16_t idx, uint8_t subidx, const ::std::chrono::milliseconds &timeout)
Queues an asynchronous read (SDO block upload) operation and creates a future which becomes ready onc...
SdoFuture< void > AsyncBlockWrite(uint16_t idx, uint8_t subidx, T &&value)
Equivalent to AsyncBlockWrite(uint16_t idx, uint8_t subidx, T&& value, const ::std::chrono::milliseco...
SdoFuture< void > AsyncWait(const duration &d)
Submits an asynchronous wait operation and creates a future which becomes ready once the wait operati...
ev::Executor GetExecutor() const noexcept final
Returns the executor used to execute event handlers for this driver, including SDO confirmation funct...
void OnSync(uint8_t, const time_point &) noexcept override
The function invoked when a SYNC message is sent/received by the master.
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.
SdoFuture< void > AsyncWait(const time_point &t)
Submits an asynchronous wait operation and creates a future which becomes ready once the wait operati...
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...
The base class for drivers for logical devices on remote CANopen nodes.
Driver & driver
A reference to the driver with which this logical device driver is registered.
An accessor providing read-only access to a CANopen object in a local object dictionary.
Definition: master.hpp:411
A mutator providing read/write access to a CANopen object in a local object dictionary.
Definition: master.hpp:358
The CANopen master.
Definition: master.hpp:50
The abstract driver interface for a logical device on a remote CANopen node.
Definition: driver.hpp:258
An abstract task executor. This class is a wrapper around #ev_exec_t*.
Definition: exec.hpp:38
A future.
Definition: future.hpp:384
This header file is part of the C++ CANopen application library; it contains the remote node driver i...
CanError
The error flags of a CAN bus, which are not mutually exclusive.
Definition: err.hpp:47
CanState
The states of a CAN node, depending on the TX/RX error count.
Definition: err.hpp:33
NmtState
The NMT states.
Definition: node.hpp:56
NmtCommand
The NMT command specifiers.
Definition: node.hpp:42