Lely core libraries 2.3.4
node.hpp
Go to the documentation of this file.
1
22#ifndef LELY_COAPP_NODE_HPP_
23#define LELY_COAPP_NODE_HPP_
24
25#include <lely/coapp/device.hpp>
26#include <lely/io2/can_net.hpp>
27#include <lely/io2/tqueue.hpp>
28
29#include <functional>
30#include <memory>
31#include <string>
32#include <utility>
33
34// The CANopen NMT master/slave service from <lely/co/nmt.h>.
35struct __co_nmt;
36
37namespace lely {
38
39namespace canopen {
40
42enum class NmtCommand {
44 START = 0x01,
46 STOP = 0x02,
48 ENTER_PREOP = 0x80,
50 RESET_NODE = 0x81,
52 RESET_COMM = 0x82
53};
54
56enum class NmtState {
58 BOOTUP = 0x00,
60 STOP = 0x04,
62 START = 0x05,
64 RESET_NODE = 0x06,
66 RESET_COMM = 0x07,
68 PREOP = 0x7f,
70 TOGGLE = 0x80
71};
72
73constexpr NmtState
74operator&(NmtState lhs, NmtState rhs) {
75 return static_cast<NmtState>(static_cast<int>(lhs) & static_cast<int>(rhs));
76}
77
78constexpr NmtState
79operator|(NmtState lhs, NmtState rhs) {
80 return static_cast<NmtState>(static_cast<int>(lhs) | static_cast<int>(rhs));
81}
82
83constexpr NmtState
84operator^(NmtState lhs, NmtState rhs) {
85 return static_cast<NmtState>(static_cast<int>(lhs) ^ static_cast<int>(rhs));
86}
87
88constexpr NmtState
89operator~(NmtState lhs) {
90 return static_cast<NmtState>(~static_cast<int>(lhs));
91}
92
93inline NmtState&
94operator&=(NmtState& lhs, NmtState rhs) noexcept {
95 return lhs = lhs & rhs;
96}
97
98inline NmtState&
99operator|=(NmtState& lhs, NmtState rhs) noexcept {
100 return lhs = lhs | rhs;
101}
102
103inline NmtState&
104operator^=(NmtState& lhs, NmtState rhs) noexcept {
105 return lhs = lhs ^ rhs;
106}
107
116class Node : public io::CanNet, public Device {
117 friend class LssMaster;
118
119 public:
120 using duration = io::TimerBase::duration;
121 using time_point = io::TimerBase::time_point;
122
143 explicit Node(ev_exec_t* exec, io::TimerBase& timer, io::CanChannelBase& chan,
144 const ::std::string& dcf_txt, const ::std::string& dcf_bin = "",
145 uint8_t id = 0xff);
146
148 explicit Node(io::TimerBase& timer, io::CanChannelBase& chan,
149 const ::std::string& dcf_txt, const ::std::string& dcf_bin = "",
150 uint8_t id = 0xff)
151 : Node(nullptr, timer, chan, dcf_txt, dcf_bin, id) {}
152
153 Node(const Node&) = delete;
154 Node& operator=(const Node&) = delete;
155
156 virtual ~Node();
157
159 ev::Executor GetExecutor() const noexcept;
160
162 io::ContextBase GetContext() const noexcept;
163
165 io::Clock GetClock() const noexcept;
166
171 void SubmitWait(const time_point& t, io_tqueue_wait& wait);
172
177 void SubmitWait(const duration& d, io_tqueue_wait& wait);
178
187 template <class F>
188 void
189 SubmitWait(const time_point& t, ev_exec_t* exec, F&& f) {
190 SubmitWait(t,
191 *io::make_timer_queue_wait_wrapper(exec, ::std::forward<F>(f)));
192 }
193
202 template <class F>
203 void
204 SubmitWait(const duration& d, ev_exec_t* exec, F&& f) {
205 SubmitWait(d,
206 *io::make_timer_queue_wait_wrapper(exec, ::std::forward<F>(f)));
207 }
208
210 template <class F>
211 typename ::std::enable_if<!::std::is_base_of<
212 io_tqueue_wait, typename ::std::decay<F>::type>::value>::type
213 SubmitWait(const time_point& t, F&& f) {
214 SubmitWait(t, nullptr, ::std::forward<F>(f));
215 }
216
218 template <class F>
219 typename ::std::enable_if<!::std::is_base_of<
220 io_tqueue_wait, typename ::std::decay<F>::type>::value>::type
221 SubmitWait(const duration& d, F&& f) {
222 SubmitWait(d, nullptr, ::std::forward<F>(f));
223 }
224
238 ev_exec_t* exec, const time_point& t, io_tqueue_wait** pwait = nullptr);
239
253 ev_exec_t* exec, const duration& d, io_tqueue_wait** pwait = nullptr);
254
257 AsyncWait(const time_point& t, io_tqueue_wait** pwait = nullptr) {
258 return AsyncWait(nullptr, t, pwait);
259 }
260
263 AsyncWait(const duration& d, io_tqueue_wait** pwait = nullptr) {
264 return AsyncWait(nullptr, d, pwait);
265 }
266
275 bool CancelWait(io_tqueue_wait& wait) noexcept;
276
284 bool AbortWait(io_tqueue_wait& wait) noexcept;
285
304 io::CanControllerBase& ctrl, int bitrate,
305 ::std::chrono::milliseconds delay);
306
313 void OnCanState(
314 ::std::function<void(io::CanState, io::CanState)> on_can_state);
315
322 void OnCanError(::std::function<void(io::CanError)> on_can_error);
323
330 void Reset();
331
341 void ConfigHeartbeat(uint8_t id, const ::std::chrono::milliseconds& ms,
342 ::std::error_code& ec);
343
354 void ConfigHeartbeat(uint8_t id, const ::std::chrono::milliseconds& ms);
355
362 void OnCommand(::std::function<void(NmtCommand)> on_command);
363
370 void OnHeartbeat(::std::function<void(uint8_t, bool)> on_heartbeat);
371
379 void OnState(::std::function<void(uint8_t, NmtState)> on_state);
380
388 void OnRpdo(
389 ::std::function<void(int, ::std::error_code, const void*, ::std::size_t)>
390 on_rpdo);
391
399 void OnRpdoError(::std::function<void(int, uint16_t, uint8_t)> on_rpdo_error);
400
408 void OnTpdo(
409 ::std::function<void(int, ::std::error_code, const void*, ::std::size_t)>
410 on_tpdo);
411
418 void OnSync(::std::function<void(uint8_t, const time_point&)> on_sync);
419
427 void OnSyncError(::std::function<void(uint16_t, uint8_t)> on_sync_error);
428
435 void OnTime(
436 ::std::function<void(const ::std::chrono::system_clock::time_point&)>
437 on_time);
438
445 void OnEmcy(
446 ::std::function<void(uint8_t, uint16_t, uint8_t, uint8_t[5])> on_emcy);
447
455 void OnSwitchBitrate(::std::function<void(int, ::std::chrono::milliseconds)>
456 on_switch_bitrate);
457
458 protected:
464 friend class Node;
465
466 public:
467 void lock() override;
468 void unlock() override;
469
470 protected:
471 TpdoEventMutex(Node& node_) noexcept : node(&node_) {}
472
473 Node* node;
474 };
475
480 __can_net* net() const noexcept;
481
483 void SetTime();
484
497 virtual void OnCanState(io::CanState new_state,
498 io::CanState old_state) noexcept;
499
507 virtual void
508 OnCanError(io::CanError error) noexcept {
509 (void)error;
510 }
511
516 __co_nmt* nmt() const noexcept;
517
518 /*
519 * Generates an EMCY error and triggers the error handling behavior according
520 * to object 1029:01 (Error behavior object) in case of a communication error
521 * (emergency error code 0x81xx).
522 *
523 * @param eec the emergency error code.
524 * @param er the error register.
525 * @param msef the manufacturer-specific error code.
526 */
527 void Error(uint16_t eec, uint8_t er,
528 const uint8_t msef[5] = nullptr) noexcept;
529
537 void RpdoRtr(int num = 0) noexcept;
538
547 void TpdoEvent(int num = 0) noexcept;
548
559 template <class T>
560 typename ::std::enable_if<is_canopen_basic<T>::value && sizeof(T) <= 4,
561 void>::type
562 DamMpdoEvent(int num, uint8_t id, uint16_t idx, uint8_t subidx, T value);
563
568 TpdoEventMutex tpdo_event_mutex;
569
570 private:
571 void on_can_state(io::CanState new_state,
572 io::CanState old_state) noexcept final;
573 void on_can_error(io::CanError error) noexcept final;
574
582 virtual void
583 OnCommand(NmtCommand cs) noexcept {
584 (void)cs;
585 }
586
598 virtual void
599 OnHeartbeat(uint8_t id, bool occurred) noexcept {
600 (void)id;
601 (void)occurred;
602 }
603
613 virtual void
614 OnState(uint8_t id, NmtState st) noexcept {
615 (void)id;
616 (void)st;
617 }
618
639 virtual void
640 OnRpdo(int num, ::std::error_code ec, const void* p,
641 ::std::size_t n) noexcept {
642 (void)num;
643 (void)ec;
644 (void)p;
645 (void)n;
646 }
647
661 virtual void
662 OnRpdoError(int num, uint16_t eec, uint8_t er) noexcept {
663 (void)num;
664 Error(eec, er);
665 }
666
686 virtual void
687 OnTpdo(int num, ::std::error_code ec, const void* p,
688 ::std::size_t n) noexcept {
689 (void)num;
690 (void)ec;
691 (void)p;
692 (void)n;
693 }
694
703 virtual void
704 OnSync(uint8_t cnt, const time_point& t) noexcept {
705 (void)cnt;
706 (void)t;
707 }
708
718 virtual void
719 OnSyncError(uint16_t eec, uint8_t er) noexcept {
720 Error(eec, er);
721 }
722
728 virtual void
729 OnTime(const ::std::chrono::system_clock::time_point& abs_time) noexcept {
730 (void)abs_time;
731 }
732
741 virtual void
742 OnEmcy(uint8_t id, uint16_t eec, uint8_t er, uint8_t msef[5]) noexcept {
743 (void)id;
744 (void)eec;
745 (void)er;
746 (void)msef;
747 }
748
757 virtual void
758 OnSwitchBitrate(int bitrate, ::std::chrono::milliseconds delay) noexcept {
759 (void)bitrate;
760 (void)delay;
761 }
762
774 virtual void OnStore(uint8_t id, int bitrate);
775
776 struct Impl_;
777 ::std::unique_ptr<Impl_> impl_;
778};
779
780} // namespace canopen
781
782} // namespace lely
783
784#endif // LELY_COAPP_NODE_HPP_
This header file is part of the I/O library; it contains the C++ interface for the timer queue.
The CANopen device description.
Definition: device.hpp:45
uint8_t id() const noexcept
Returns the node-ID.
Definition: device.cpp:193
The base class for CANopen LSS masters.
A recursive mutex-like object that can be used to postpone the transmission of acyclic and event-driv...
Definition: node.hpp:463
void lock() override
Blocks until a lock can be obtained for the current execution agent (thread, process,...
Definition: node.cpp:396
void unlock() override
Releases the lock held by the execution agent. Throws no exceptions.
Definition: node.cpp:403
The base class for CANopen nodes.
Definition: node.hpp:116
ev::Future< void, ::std::exception_ptr > AsyncWait(const time_point &t, io_tqueue_wait **pwait=nullptr)
Equivalent to AsyncWait(nullptr, t, pwait).
Definition: node.hpp:257
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:185
void Reset()
(Re)starts the node.
Definition: node.cpp:258
void OnSyncError(::std::function< void(uint16_t, uint8_t)> on_sync_error)
Registers the function to be invoked when the data length of a received SYNC message does not match.
Definition: node.cpp:352
void OnSync(::std::function< void(uint8_t, const time_point &)> on_sync)
Registers the function to be invoked when a SYNC message is sent/received.
Definition: node.cpp:342
void OnState(::std::function< void(uint8_t, NmtState)> on_state)
Registers the function to be invoked when an NMT state change or boot-up event is detected for a remo...
Definition: node.cpp:302
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:270
void SetTime()
Updates the CAN network time.
Definition: node.cpp:415
void OnCanError(::std::function< void(io::CanError)> on_can_error)
Registers the function to be invoked when an error is detected on the CAN bus.
Definition: node.cpp:252
void OnCommand(::std::function< void(NmtCommand)> on_command)
Registers the function to be invoked when an NMT command is received from the master.
Definition: node.cpp:290
void OnSwitchBitrate(::std::function< void(int, ::std::chrono::milliseconds)> on_switch_bitrate)
Registers the function to be invoked when the LSS master activates the bit rate of all CANopen device...
Definition: node.cpp:385
Node(ev_exec_t *exec, io::TimerBase &timer, io::CanChannelBase &chan, const ::std::string &dcf_txt, const ::std::string &dcf_bin="", uint8_t id=0xff)
Creates a new CANopen node.
Definition: node.cpp:145
__co_nmt * nmt() const noexcept
Returns a pointer to the internal CANopen NMT master/slave service from <lely/co/nmt....
Definition: node.cpp:434
ev::Future< void, ::std::exception_ptr > AsyncWait(const duration &d, io_tqueue_wait **pwait=nullptr)
Equivalent to AsyncWait(nullptr, d, pwait).
Definition: node.hpp:263
io::ContextBase GetContext() const noexcept
Returns the underlying I/O context with which this context is registered.
Definition: node.cpp:164
void TpdoEvent(int num=0) noexcept
Triggers the transmission of an acyclic or event-driven PDO.
Definition: node.cpp:457
void OnHeartbeat(::std::function< void(uint8_t, bool)> on_heartbeat)
Registers the function to be invoked when a heartbeat timeout event occurs or is resolved.
Definition: node.cpp:296
ev::Future< void, ::std::exception_ptr > AsyncSwitchBitrate(io::CanControllerBase &ctrl, int bitrate, ::std::chrono::milliseconds delay)
Stops the specified CAN controller and submits asynchronous operations to wait for the delay period,...
Definition: node.cpp:213
typename::std::enable_if<!::std::is_base_of< io_tqueue_wait, typename::std::decay< F >::type >::value >::type SubmitWait(const time_point &t, F &&f)
Equivalent to SubmitWait(t, nullptr, f).
Definition: node.hpp:213
__can_net * net() const noexcept
Returns a pointer to the internal CAN network interface from <lely/can/net.h>.
Definition: node.cpp:410
ev::Executor GetExecutor() const noexcept
Returns the executor used to process I/O and CANopen events.
Definition: node.cpp:159
void OnTime(::std::function< void(const ::std::chrono::system_clock::time_point &)> on_time)
Registers the function to be invoked when a TIME message is received.
Definition: node.cpp:362
void OnRpdo(::std::function< void(int, ::std::error_code, const void *, ::std::size_t)> on_rpdo)
Registers the function to be invoked when a Receive-PDO is processed.
Definition: node.cpp:308
void SubmitWait(const duration &d, ev_exec_t *exec, F &&f)
Submits a wait operation.
Definition: node.hpp:204
void OnRpdoError(::std::function< void(int, uint16_t, uint8_t)> on_rpdo_error)
Registers the function to be invoked when a Receive-PDO length mismatch or timeout error occurs.
Definition: node.cpp:320
void OnTpdo(::std::function< void(int, ::std::error_code, const void *, ::std::size_t)> on_tpdo)
Registers the function to be invoked after a Transmit-PDO is sent or an error occurs.
Definition: node.cpp:330
io::Clock GetClock() const noexcept
Returns the clock used by the timer.
Definition: node.cpp:169
bool AbortWait(io_tqueue_wait &wait) noexcept
Aborts the specified wait operation if it is pending.
Definition: node.cpp:208
typename::std::enable_if<!::std::is_base_of< io_tqueue_wait, typename::std::decay< F >::type >::value >::type SubmitWait(const duration &d, F &&f)
Equivalent to SubmitWait(d, nullptr, f).
Definition: node.hpp:221
Node(io::TimerBase &timer, io::CanChannelBase &chan, const ::std::string &dcf_txt, const ::std::string &dcf_bin="", uint8_t id=0xff)
Creates a new CANopen node.
Definition: node.hpp:148
void OnEmcy(::std::function< void(uint8_t, uint16_t, uint8_t, uint8_t[5])> on_emcy)
Registers the function to be invoked when an EMCY message is received.
Definition: node.cpp:374
void OnCanState(::std::function< void(io::CanState, io::CanState)> on_can_state)
Registers the function to be invoked when a CAN bus state change is detected.
Definition: node.cpp:245
void SubmitWait(const time_point &t, io_tqueue_wait &wait)
Submits a wait operation.
Definition: node.cpp:174
void RpdoRtr(int num=0) noexcept
Requests the transmission of a PDO by sending a CAN frame with the RTR (Remote Transmission Request) ...
Definition: node.cpp:444
bool CancelWait(io_tqueue_wait &wait) noexcept
Cancels the specified wait operation if it is pending.
Definition: node.cpp:203
The type of objects thrown as exceptions to report a system error with an associated error code.
Definition: exception.hpp:54
An abstract task executor. This class is a wrapper around #ev_exec_t*.
Definition: exec.hpp:38
A future.
Definition: future.hpp:384
A reference to an abstract CAN channel.
Definition: can.hpp:430
A reference to an abstract CAN controller.
Definition: can.hpp:286
A CAN network interface. This class is a wrapper around io_can_net_t*.
Definition: can_net.hpp:38
virtual void on_can_error(CanError error) noexcept
The function invoked when an error is detected on the CAN bus.
Definition: can_net.hpp:208
virtual void on_can_state(CanState new_state, CanState old_state) noexcept
The function invoked when a CAN bus state change is detected.
Definition: can_net.hpp:191
A reference to an abstract timer.
Definition: timer.hpp:130
An abstract interface conforming to the BasicLockable concept.
Definition: mutex.hpp:34
This header file is part of the C++ CANopen application library; it contains the CANopen device descr...
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
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
Definition: ev.h:29
NmtState
The NMT states.
Definition: node.hpp:56
@ TOGGLE
The mask to get/set the toggle bit from an NMT state.
@ PREOP
Pre-operational.
NmtCommand
The NMT command specifiers.
Definition: node.hpp:42
@ ENTER_PREOP
Enter pre-operational.
@ RESET_COMM
Reset communication.
STL namespace.
A CAN network interface.
Definition: net.c:37
A CANopen NMT master/slave service.
Definition: nmt.c:148
A wait operation suitable for use with a timer queue.
Definition: tqueue.h:36
If T is one of the CANopen basic types, provides the member constant value equal to true.
This header file is part of the I/O library; it contains the C++ interface for the timer queue.