Lely core libraries  2.3.4
logical_driver.cpp
Go to the documentation of this file.
1 
24 #include "coapp.hpp"
25 
26 #if !LELY_NO_COAPP_MASTER
27 
29 
30 namespace lely {
31 
32 namespace canopen {
33 
34 BasicLogicalDriver<BasicDriver>::BasicLogicalDriver(BasicDriver& driver_,
35  int num, uint32_t dev)
36  : master(driver_.master),
37  driver(driver_),
38  rpdo_mapped(*this),
39  tpdo_mapped(*this),
40  tpdo_event_mutex(driver_.tpdo_event_mutex),
41  num_(num),
42  dev_(dev) {
43  driver.Insert(*this);
44 }
45 
46 BasicLogicalDriver<BasicDriver>::~BasicLogicalDriver() { driver.Erase(*this); }
47 
48 SdoFuture<void>
49 BasicLogicalDriver<BasicDriver>::AsyncConfig() {
50  SdoFuture<void> f;
51  // A convenience function which reads and copies the device type from object
52  // 67FF:00 (adjusted for logical device number) in the remote object
53  // dictionary.
54  auto read_67ff = [this]() {
55  return AsyncRead<uint32_t>(0x67ff, 0).then(
56  GetExecutor(),
57  [this](SdoFuture<uint32_t> f) { dev_ = f.get().value(); });
58  };
59  if (num_ == 1) {
60  // A convenience function which checks and copies the value of the
61  // (expected) device type or, if it indicates multiple logical devices,
62  // reads the value from object 67FF:00 in the remote object dictionary.
63  auto check_1000 = [this, read_67ff](uint32_t value) -> SdoFuture<void> {
64  if ((value) >> 16 == 0xffff) return read_67ff();
65  dev_ = value;
66  return make_empty_sdo_future();
67  };
68  ::std::error_code ec;
69  // Try to read the expected device type from the local object dictionary
70  // (object 1F84:$NODEID).
71  auto value = driver.master[0x1f84][driver.id()].Read<uint32_t>(ec);
72  if (!ec) {
73  f = check_1000(value);
74  } else {
75  // If the expected device type is not available, read the device type from
76  // the remote object dictionary (object 1000:00).
77  f = AsyncRead<uint32_t>(0x1000, 0).then(
78  GetExecutor(), [check_1000](SdoFuture<uint32_t> f) {
79  return check_1000(f.get().value());
80  });
81  }
82  } else {
83  // This is not the first logical device. Read and copy the device type from
84  // object 67FF:00 (adjusted for logical device number) in the remote object
85  // dictionary.
86  f = read_67ff();
87  }
88  // Run OnConfig() after the device type has been obtained.
89  return f.then(GetExecutor(), [this](SdoFuture<void> f) {
90  // Throw an exception if an SDO error occurred.
91  f.get().value();
92  // Only invoke OnConfig() if the previous operations succeeded.
93  SdoPromise<void> p;
94  OnConfig([p](::std::error_code ec) mutable {
95  p.set(::std::make_exception_ptr(::std::system_error(ec, "OnConfig")));
96  });
97  return p.get_future();
98  });
99 }
100 
101 SdoFuture<void>
102 BasicLogicalDriver<BasicDriver>::AsyncDeconfig() {
103  SdoPromise<void> p;
104  // Post a task for OnDeconfig() to ensure this function does not block.
105  GetExecutor().post([this, p]() mutable {
106  OnDeconfig([p](::std::error_code ec) mutable {
107  p.set(::std::make_exception_ptr(::std::system_error(ec, "OnDeconfig")));
108  });
109  });
110  return p.get_future();
111 }
112 
113 } // namespace canopen
114 
115 } // namespace lely
116 
117 #endif // !LELY_NO_COAPP_MASTER
This is the internal header file of the C++ CANopen application library.
This header file is part of the C++ CANopen application library; it contains the logical device drive...
SdoFuture< void > make_empty_sdo_future()
Returns an SDO future with a shared state that is immediately ready, containing a successful result o...
Definition: sdo.hpp:73