Lely core libraries
2.2.5
|
Go to the documentation of this file.
48 void OnCsInd(
CONMT* nmt, uint8_t cs) noexcept;
49 void OnHbInd(
CONMT* nmt, uint8_t
id,
int state,
int reason) noexcept;
50 void OnStInd(
CONMT* nmt, uint8_t
id, uint8_t st) noexcept;
52 void OnRpdoInd(
CORPDO* pdo, uint32_t ac,
const void* ptr,
size_t n) noexcept;
53 void OnRpdoErr(
CORPDO* pdo, uint16_t eec, uint8_t er) noexcept;
55 void OnTpdoInd(
COTPDO* pdo, uint32_t ac,
const void* ptr,
size_t n) noexcept;
57 void OnSyncInd(
CONMT* nmt, uint8_t cnt) noexcept;
58 void OnSyncErr(
COSync* sync, uint16_t eec, uint8_t er) noexcept;
60 void OnTimeInd(
COTime* time,
const timespec* tp) noexcept;
62 void OnEmcyInd(
COEmcy* emcy, uint8_t
id, uint16_t ec, uint8_t er,
63 uint8_t msef[5]) noexcept;
65 void OnRateInd(
COLSS*, uint16_t rate,
int delay) noexcept;
66 int OnStoreInd(
COLSS*, uint8_t
id, uint16_t rate) noexcept;
68 void RpdoRtr(
int num) noexcept;
78 ::std::function<void(uint8_t,
bool)> on_heartbeat;
79 ::std::function<void(uint8_t,
NmtState)> on_state;
80 ::std::function<void(
int, ::std::error_code,
const void*, ::std::size_t)>
82 ::std::function<void(
int, uint16_t, uint8_t)> on_rpdo_error;
83 ::std::function<void(
int, ::std::error_code,
const void*, ::std::size_t)>
85 ::std::function<void(uint8_t,
const time_point&)> on_sync;
86 ::std::function<void(uint16_t, uint8_t)> on_sync_error;
87 ::std::function<void(const ::std::chrono::system_clock::time_point&)> on_time;
88 ::std::function<void(uint8_t, uint16_t, uint8_t, uint8_t[5])> on_emcy;
89 ::std::function<void(
int, ::std::chrono::milliseconds)> on_switch_bitrate;
93 const ::std::string& dcf_txt, const ::std::string& dcf_bin,
95 : io::CanNet(exec, timer, chan, 0, 0),
96 Device(dcf_txt, dcf_bin, id, this),
97 tpdo_event_mutex(*this),
103 Node::~Node() =
default;
122 wait.
value = util::to_timespec(t);
134 auto value = util::to_timespec(t);
136 if (!f) util::throw_errc(
"AsyncWait");
140 if (errc) util::throw_errc(
"AsyncWait", errc);
161 ::std::chrono::milliseconds delay) {
173 [
this, &ctrl, bitrate,
195 ::std::lock_guard<util::BasicLockable>
lock(*
this);
201 ::std::lock_guard<util::BasicLockable>
lock(*
this);
207 ::std::lock_guard<util::BasicLockable>
lock(*
this);
218 ::std::error_code& ec) {
219 ::std::lock_guard<util::BasicLockable>
lock(*
this);
231 ::std::error_code ec;
238 ::std::lock_guard<util::BasicLockable>
lock(*
this);
239 impl_->on_command = on_command;
244 ::std::lock_guard<util::BasicLockable>
lock(*
this);
245 impl_->on_heartbeat = on_heartbeat;
250 ::std::lock_guard<util::BasicLockable>
lock(*
this);
251 impl_->on_state = on_state;
256 ::std::function<
void(
int, ::std::error_code,
const void*, ::std::size_t)>
258 ::std::lock_guard<util::BasicLockable>
lock(*
this);
259 impl_->on_rpdo = on_rpdo;
264 ::std::lock_guard<util::BasicLockable>
lock(*
this);
265 impl_->on_rpdo_error = on_rpdo_error;
270 ::std::function<
void(
int, ::std::error_code,
const void*, ::std::size_t)>
272 ::std::lock_guard<util::BasicLockable>
lock(*
this);
273 impl_->on_tpdo = on_tpdo;
277 Node::OnSync(::std::function<
void(uint8_t,
const time_point&)> on_sync) {
278 ::std::lock_guard<util::BasicLockable>
lock(*
this);
279 impl_->on_sync = on_sync;
284 ::std::lock_guard<util::BasicLockable>
lock(*
this);
285 impl_->on_sync_error = on_sync_error;
290 ::std::function<
void(const ::std::chrono::system_clock::time_point&)>
292 ::std::lock_guard<util::BasicLockable>
lock(*
this);
293 impl_->on_time = on_time;
298 ::std::function<
void(uint8_t, uint16_t, uint8_t, uint8_t[5])> on_emcy) {
299 ::std::lock_guard<util::BasicLockable>
lock(*
this);
300 impl_->on_emcy = on_emcy;
305 ::std::function<
void(
int, ::std::chrono::milliseconds)> on_switch_bitrate) {
306 ::std::lock_guard<util::BasicLockable>
lock(*
this);
307 impl_->on_switch_bitrate = on_switch_bitrate;
312 node->impl_->nmt->onTPDOEventLock();
317 node->impl_->nmt->onTPDOEventUnlock();
332 assert(new_state != old_state);
335 if (new_state == io::CanState::PASSIVE) {
338 }
else if (old_state == io::CanState::BUSOFF) {
346 return impl_->nmt.get();
350 Node::Error(uint16_t eec, uint8_t er,
const uint8_t msef[5]) noexcept {
351 impl_->nmt->onErr(eec, er, msef);
359 for (num = 1; num <= 512; num++) impl_->RpdoRtr(num);
365 impl_->nmt->onTPDOEvent(num);
371 if (impl_->on_can_state) {
372 auto f = impl_->on_can_state;
374 f(new_state, old_state);
381 if (impl_->on_can_error) {
382 auto f = impl_->on_can_error;
390 util::throw_error_code(
"OnStore", ::std::errc::operation_not_supported);
395 nmt->setCsInd<Impl_, &Impl_::OnCsInd>(
this);
396 nmt->setHbInd<Impl_, &Impl_::OnHbInd>(
this);
397 nmt->setStInd<Impl_, &Impl_::OnStInd>(
this);
399 nmt->setSyncInd<Impl_, &Impl_::OnSyncInd>(
this);
403 Node::Impl_::OnCsInd(
CONMT* nmt, uint8_t cs) noexcept {
405 auto lss = nmt->getLSS();
407 lss->setRateInd<Impl_, &Impl_::OnRateInd>(
this);
408 lss->setStoreInd<Impl_, &Impl_::OnStoreInd>(
this);
413 auto sync = nmt->getSync();
414 if (sync) sync->setErr<Impl_, &Impl_::OnSyncErr>(
this);
415 auto time = nmt->getTime();
416 if (time) time->setInd<Impl_, &Impl_::OnTimeInd>(
this);
417 auto emcy = nmt->getEmcy();
418 if (emcy) emcy->setInd<Impl_, &Impl_::OnEmcyInd>(
this);
422 for (
int i = 1; i <= 512; i++) {
423 auto pdo = nmt->getRPDO(i);
425 pdo->setInd<Impl_, &Impl_::OnRpdoInd>(
this);
426 pdo->setErr<Impl_, &Impl_::OnRpdoErr>(
this);
429 for (
int i = 1; i <= 512; i++) {
430 auto pdo = nmt->getTPDO(i);
431 if (pdo) pdo->setInd<Impl_, &Impl_::OnTpdoInd>(
this);
436 self->UpdateRpdoMapping();
437 self->UpdateTpdoMapping();
444 util::UnlockGuard<util::BasicLockable> unlock(*
self);
450 Node::Impl_::OnHbInd(CONMT* nmt, uint8_t
id,
int state,
int reason) noexcept {
452 nmt->onHb(
id, state, reason);
457 self->OnHeartbeat(
id, occurred);
460 auto f = on_heartbeat;
461 util::UnlockGuard<util::BasicLockable> unlock(*
self);
467 Node::Impl_::OnStInd(CONMT* nmt, uint8_t
id, uint8_t st) noexcept {
471 if (
id == nmt->getDev()->getId())
return;
473 self->OnState(
id,
static_cast<NmtState>(st));
477 util::UnlockGuard<util::BasicLockable> unlock(*
self);
483 Node::Impl_::OnRpdoInd(CORPDO* pdo, uint32_t ac,
const void* ptr,
485 int num = pdo->getNum();
486 self->OnRpdo(num,
static_cast<SdoErrc>(ac), ptr, n);
490 util::UnlockGuard<util::BasicLockable> unlock(*
self);
491 f(num,
static_cast<SdoErrc>(ac), ptr, n);
496 Node::Impl_::OnRpdoErr(CORPDO* pdo, uint16_t eec, uint8_t er) noexcept {
497 int num = pdo->getNum();
498 self->OnRpdoError(num, eec, er);
501 auto f = on_rpdo_error;
502 util::UnlockGuard<util::BasicLockable> unlock(*
self);
508 Node::Impl_::OnTpdoInd(COTPDO* pdo, uint32_t ac,
const void* ptr,
510 int num = pdo->getNum();
511 self->OnTpdo(num,
static_cast<SdoErrc>(ac), ptr, n);
515 util::UnlockGuard<util::BasicLockable> unlock(*
self);
516 f(num,
static_cast<SdoErrc>(ac), ptr, n);
521 Node::Impl_::OnSyncInd(CONMT*, uint8_t cnt) noexcept {
522 auto t =
self->GetClock().gettime();
523 self->OnSync(cnt, t);
527 util::UnlockGuard<util::BasicLockable> unlock(*
self);
533 Node::Impl_::OnSyncErr(COSync*, uint16_t eec, uint8_t er) noexcept {
534 self->OnSyncError(eec, er);
537 auto f = on_sync_error;
538 util::UnlockGuard<util::BasicLockable> unlock(*
self);
544 Node::Impl_::OnTimeInd(COTime*,
const timespec* tp) noexcept {
546 ::std::chrono::system_clock::time_point abs_time(util::from_timespec(*tp));
547 self->OnTime(abs_time);
551 util::UnlockGuard<util::BasicLockable> unlock(*
self);
557 Node::Impl_::OnEmcyInd(COEmcy*, uint8_t
id, uint16_t ec, uint8_t er,
558 uint8_t msef[5]) noexcept {
559 self->OnEmcy(
id, ec, er, msef);
563 util::UnlockGuard<util::BasicLockable> unlock(*
self);
569 Node::Impl_::OnRateInd(COLSS*, uint16_t rate,
int delay) noexcept {
570 self->OnSwitchBitrate(rate * 1000, ::std::chrono::milliseconds(delay));
572 if (on_switch_bitrate) {
573 auto f = on_switch_bitrate;
574 util::UnlockGuard<util::BasicLockable> unlock(*
self);
575 f(rate * 1000, ::std::chrono::milliseconds(delay));
580 Node::Impl_::OnStoreInd(COLSS*, uint8_t
id, uint16_t rate) noexcept {
582 self->OnStore(
id, rate * 1000);
590 Node::Impl_::RpdoRtr(
int num) noexcept {
591 auto pdo = nmt->getRPDO(num);
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.
struct timespec value
The absolute expiration time.
void io_tqueue_submit_wait(io_tqueue_t *tq, struct io_tqueue_wait *wait)
Submits a wait operation to a timer queue.
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.
NmtCommand
The NMT command specifiers.
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
bool AbortWait(io_tqueue_wait &wait) noexcept
Aborts the specified wait operation if it is pending.
void set_time()
Updates the CAN network time.
void OnState(::std::function< void(uint8_t, NmtState)> on_state)
Registers the function to be invoked whenan NMT state change or boot-up event is detected for a remot...
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...
A reference to an abstract timer.
The internal implementation of the CANopen node.
A mutex wrapper that provides a convenient RAII-style mechanism for releasing a mutex for the duratio...
void RpdoRtr(int num=0) noexcept
Requests the transmission of a PDO by sending a CAN frame with the RTR (Remote Transmission Request) ...
::std::unique_ptr< T, delete_c_type< T > > unique_c_ptr
A specialization of std::unique_ptr for trivial, standard layout or incomplete C types,...
A refence to an I/O context. This class is a wrapper around #io_ctx_t*.
void Reset()
(Re)starts the node.
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
The type of objects thrown as exceptions to report a system error with an associated error code.
An opaque CANopen Receive-PDO service type.
A reference to an abstract CAN channel.
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.
An opaque CANopen NMT master/slave service type.
@ CO_NMT_EC_TIMEOUT
An NMT error control timeout event.
co_unsigned32_t co_dev_cfg_hb(co_dev_t *dev, co_unsigned8_t id, co_unsigned16_t ms)
Configures heartbeat consumption for the specified node by updating CANopen object 1016 (Consumer hea...
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.
ev::Executor get_executor() const noexcept
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.
CanError
The error flags of a CAN bus, which are not mutually exclusive.
#define CO_NMT_CS_START
The NMT command specifier 'start'.
CanState
The states of a CAN node, depending on the TX/RX error count.
void on_can_state(io::CanState new_state, io::CanState old_state) noexcept final
The function invoked when a CAN bus state change is detected.
void unlock() override
Releases the lock held by the execution agent. Throws no exceptions.
virtual void OnStore(uint8_t id, int bitrate)
The function invoked then a request is received from the LSS master to store the pending node-ID and ...
void stop(::std::error_code &ec) noexcept
void TpdoEvent(int num=0) noexcept
Triggers the transmission of an acyclic or event-driven PDO.
A wait operation suitable for use with a timer queue.
ev_future_t * io_tqueue_async_wait(io_tqueue_t *tq, ev_exec_t *exec, const struct timespec *value, struct io_tqueue_wait **pwait)
Submits an asynchronous wait operation to a timer queue and creates a future which becomes ready once...
Clock get_clock() const noexcept
An opaque CANopen Transmit-PDO service type.
void lock() final
Blocks until a lock can be obtained for the current execution agent (thread, process,...
uint8_t id() const noexcept
Returns the node-ID.
An opaque CANopen TIME producer/consumer service type.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
An opaque CANopen SYNC producer/consumer service type.
An abstract task executor. This class is a wrapper around #ev_exec_t*.
void restart(::std::error_code &ec) noexcept
void OnCommand(::std::function< void(NmtCommand)> on_command)
Registers the function to be invoked when an NMT command is received from the master.
void set_bitrate(int nominal, int data, ::std::error_code &ec) noexcept
CODev * dev() const noexcept
Returns a pointer to the internal CANopen device from <lely/co/dev.hpp>.
An opaque CAN network interface type.
bool CancelWait(io_tqueue_wait &wait) noexcept
Cancels the specified wait operation if it is pending.
The CANopen device description.
#define CO_NMT_CS_ENTER_PREOP
The NMT command specifier 'enter pre-operational'.
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.
ContextBase get_ctx() const noexcept
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.
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.
result_type & get()
Returns the result of a ready future.
size_t io_tqueue_abort_wait(io_tqueue_t *tq, struct io_tqueue_wait *wait)
Aborts the specified timer queue wait operation if it is pending.
SdoErrc
The SDO abort codes.
io::ContextBase GetContext() const noexcept
Returns the underlying I/O context with which this context is registered.
@ CO_NMT_EC_OCCURRED
An NMT error control event occurred.
io::Clock GetClock() const noexcept
Returns the clock used by the timer.
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...
CANNet * net() const noexcept
Returns a pointer to the internal CAN network interface from <lely/can/net.hpp>.
The base class for CANopen nodes.
ev::Executor GetExecutor() const noexcept
Returns the executor used to process I/O and CANopen events.
#define CO_NMT_CS_RESET_NODE
The NMT command specifier 'reset node'.
The type of exception thrown when an SDO abort code is received.
An abstract clock. This class is a wrapper around #io_clock_t*.
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.
void unlock() final
Releases the lock held by the execution agent. Throws no exceptions.
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.
void on_can_error(io::CanError error) noexcept final
The function invoked when an error is detected on the CAN bus.
A reference to an abstract CAN controller.
void SubmitWait(const time_point &t, io_tqueue_wait &wait)
Submits a wait operation.
An opaque CANopen LSS master/slave service type.
size_t io_tqueue_cancel_wait(io_tqueue_t *tq, struct io_tqueue_wait *wait)
Cancels the specified timer queue wait operation if it is pending.
void SetTime()
Updates the CAN network time.
An opaque CANopen EMCY producer/consumer service type.
void lock() override
Blocks until a lock can be obtained for the current execution agent (thread, process,...
#define CO_NMT_CS_RESET_COMM
The NMT command specifier 'reset communication'.
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.
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...
unique_c_ptr< T > make_unique_c(Args &&... args)
Creates an instance of a trivial, standard layout or incomplete C type and wraps it in a lely::unique...
CONMT * nmt() const noexcept
Returns a pointer to the internal CANopen NMT master/slave service from <lely/co/nmt....
An opaque CANopen device type.
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,...