26 #if !LELY_NO_COAPP_MASTER 42 rpdo_mapped(master.RpdoMapped(id)),
43 tpdo_mapped(master.TpdoMapped(id)),
44 tpdo_event_mutex(master.tpdo_event_mutex),
45 exec_(exec ? exec : static_cast<
ev_exec_t*>(master.GetExecutor())),
50 BasicDriver::~BasicDriver() {
master.
Erase(*
this); }
55 throw ::std::out_of_range(
"invalid logical device number: " +
56 ::std::to_string(driver.
Number()));
57 if (find(driver.
id()) != end())
58 throw ::std::out_of_range(
"logical device number " +
59 ::std::to_string(driver.
Number()) +
60 " already registered");
62 MapType::operator[](driver.
Number()) = &driver;
67 auto it = find(driver.
Number());
68 if (it != end() && it->second == &driver) erase(it);
75 if (it != end())
return it->second->AsyncConfig();
76 }
else if (size() == 1) {
78 return begin()->second->AsyncConfig();
79 }
else if (!empty()) {
80 ::std::array<SdoFuture<void>, 8> futures;
83 for (
const auto& it : *
this) futures[n++] = it.second->AsyncConfig();
86 ::std::array<ev_future_t*, 8> tmp;
87 ::std::copy(futures.begin(), futures.end(), tmp.begin());
93 for (
const auto& it : futures) {
95 if (it) it.get().value();
106 if (it != end())
return it->second->AsyncDeconfig();
107 }
else if (size() == 1) {
109 return begin()->second->AsyncDeconfig();
110 }
else if (!empty()) {
111 ::std::array<SdoFuture<void>, 8> futures;
114 for (
const auto& it : *
this) futures[n++] = it.second->AsyncDeconfig();
118 ::std::array<ev_future_t*, 8> tmp;
119 ::std::copy(futures.begin(), futures.end(), tmp.begin());
125 for (
const auto& it : futures) {
127 if (it) it.get().value();
137 for (
const auto& it : *
this) it.second->OnCanState(new_state, old_state);
142 for (
const auto& it : *
this) it.second->OnCanError(
error);
147 if (idx >= 0x6000 && idx <= 0x9fff) {
148 int num = (idx - 0x6000) / 0x800 + 1;
150 if (it != end()) it->second->OnRpdoWrite(idx - (num - 1) * 0x800, subidx);
152 for (
const auto& it : *
this) it.second->OnRpdoWrite(idx, subidx);
158 for (
const auto& it : *
this) it.second->OnCommand(cs);
163 for (
const auto& it : *
this) it.second->OnNodeGuarding(occurred);
168 for (
const auto& it : *
this) it.second->OnHeartbeat(occurred);
173 for (
const auto& it : *
this) it.second->OnState(st);
178 for (
const auto& it : *
this) it.second->OnBoot(st, es, what);
183 ::std::function<
void(::std::error_code ec)> res) noexcept {
186 res(::std::error_code{});
193 ::std::error_code ec;
194 auto& result = f.get();
195 if (result.has_error()) {
197 ::std::rethrow_exception(result.error());
198 }
catch (const ::std::system_error& e) {
206 }
catch (::std::system_error& e) {
214 ::std::function<
void(::std::error_code ec)> res) noexcept {
217 res(::std::error_code{});
224 ::std::error_code ec;
225 auto& result = f.get();
226 if (result.has_error()) {
228 ::std::rethrow_exception(result.error());
229 }
catch (const ::std::system_error& e) {
237 }
catch (::std::system_error& e) {
245 for (
const auto& it : *
this) it.second->OnSync(cnt, t);
250 for (
const auto& it : *
this) it.second->OnSyncError(eec, er);
255 const ::std::chrono::system_clock::time_point& abs_time) noexcept {
256 for (
const auto& it : *
this) it.second->OnTime(abs_time);
261 for (
const auto& it : *
this) it.second->OnEmcy(eec, er, msef);
268 #endif // !LELY_NO_COAPP_MASTER const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
ev::Executor GetExecutor() const noexcept final
Returns the executor used to execute event handlers for this driver, including SDO confirmation funct...
BasicDriver(ev_exec_t *exec, BasicMaster &master, uint8_t id)
Creates a new driver for a remote CANopen node and registers it with the master.
void OnSync(uint8_t cnt, const time_point &t) noexcept override
The default implementation notifies all registered logical device drivers.
This is the internal header file of the C++ CANopen application library.
NmtCommand
The NMT command specifiers.
void OnNodeGuarding(bool occurred) noexcept override
The default implementation notifies all registered logical device drivers.
virtual uint8_t id() const noexcept=0
Returns the node-ID.
void OnDeconfig(::std::function< void(::std::error_code ec)> res) noexcept override
The default implementation invokes AsyncDeconfig() to start the deconfiguration process for all regis...
CanState
The states of a CAN node, depending on the TX/RX error count.
void OnCanState(io::CanState new_state, io::CanState old_state) noexcept override
The default implementation notifies all registered logical device drivers.
void Insert(LogicalDriverBase &driver)
Registers a logical device driver for the remote node.
SdoFuture< void > AsyncDeconfig(int num=0)
Invokes LogicalDriverBase::AsyncDeconfig() for the specified logical device driver.
SdoFuture< void > AsyncConfig(int num=0)
Invokes LogicalDriverBase::AsyncConfig() for the specified logical device driver. ...
void OnSyncError(uint16_t eec, uint8_t er) noexcept override
The default implementation notifies all registered logical device drivers.
virtual int Number() const noexcept=0
Returns the number of the logical device on the remote node.
CanError
The error flags of a CAN bus, which are not mutually exclusive.
void OnBoot(NmtState st, char es, const ::std::string &what) noexcept override
The default implementation notifies all registered logical device drivers.
The type of objects thrown as exceptions to report a system error with an associated error code...
This header file is part of the C++ CANopen application library; it contains the remote node driver i...
void OnState(NmtState st) noexcept override
The default implementation notifies all registered logical device drivers.
void OnCanError(io::CanError error) noexcept override
The default implementation notifies all registered logical device drivers.
void Insert(DriverBase &driver)
Registers a driver for a remote CANopen node.
BasicMaster & master
A reference to the master with which this driver is registered.
void OnHeartbeat(bool occurred) noexcept override
The default implementation notifies all registered logical device drivers.
void OnCommand(NmtCommand cs) noexcept override
The default implementation notifies all registered logical device drivers.
void OnTime(const ::std::chrono::system_clock::time_point &abs_time) noexcept override
The default implementation notifies all registered logical device drivers.
void Erase(LogicalDriverBase &driver)
Unregisters a logical device driver for the remote node.
SdoFuture< void > make_empty_sdo_future()
Returns an SDO future with a shared state that is immediately ready, containing a successful result o...
void OnConfig(::std::function< void(::std::error_code ec)> res) noexcept override
The default implementation invokes AsyncConfig() to start the configuration process for all registere...
The abstract driver interface for a logical device on a remote CANopen node.
void OnEmcy(uint16_t eec, uint8_t er, uint8_t msef[5]) noexcept override
The default implementation notifies all registered logical device drivers.
void OnRpdoWrite(uint16_t idx, uint8_t subidx) noexcept override
The default implementation notifies all registered logical device drivers, unless the object index is...
void Erase(DriverBase &driver)
Unregisters a driver for a remote CANopen node.