Lely core libraries 2.3.5
logical_driver.cpp
Go to the documentation of this file.
1
23
24#include "coapp.hpp"
25
26#if !LELY_NO_COAPP_MASTER
27
29
30namespace lely {
31
32namespace canopen {
33
34BasicLogicalDriver<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
46BasicLogicalDriver<BasicDriver>::~BasicLogicalDriver() { driver.Erase(*this); }
47
48SdoFuture<void>
49BasicLogicalDriver<BasicDriver>::AsyncConfig() {
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(
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.
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
102BasicLogicalDriver<BasicDriver>::AsyncDeconfig() {
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
The base class for drivers for remote CANopen nodes.
Definition driver.hpp:279
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...
SdoFuture< T > AsyncRead(uint16_t idx, uint8_t subidx)
Equivalent to AsyncRead(uint16_t idx, uint8_t subidx, const ::std::chrono::milliseconds& timeout),...
BasicDriver & driver
A reference to the driver with which this logical device driver is registered.
void OnDeconfig(::std::function< void(::std::error_code ec)> res) noexcept override
The function invoked by BasicMaster::AsyncDeconfig() to start the deconfiguration process.
ev::Executor GetExecutor() const noexcept final
Returns the executor used to execute event handlers for this driver, including SDO confirmation funct...
AsyncTask< F, Future >::future_type then(ev_exec_t *exec, F &&f)
Attaches a continuation function to a future and returns a new future which becomes ready once the co...
Definition future.hpp:558
result_type & get()
Returns the result of a ready future.
Definition future.hpp:490
Future< T, E > get_future() const noexcept
Returns a lely::ev::Future with (a reference to) the same shared state as *this.
Definition future.hpp:188
bool set(U &&u)
Satisfies a promise, if it was not aready satisfied, and stores the specified value as the result in ...
Definition future.hpp:166
value_type & value()
Returns a reference to the value if *this contains a value, and throws an exception if *this contains...
Definition result.hpp:274
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...
The namespace for the C++ CANopen application library.
Definition device.hpp:39
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
ev::Promise< T, ::std::exception_ptr > SdoPromise
A helper alias template for the type of promise used to store the result of an asynchronous SDO reque...
Definition sdo.hpp:55
ev::Future< T, ::std::exception_ptr > SdoFuture
A helper alias template for the type of future used to retrieve the result of an asynchronous SDO req...
Definition sdo.hpp:64