ICanOpenNode Interface¶
A single CANopen node running on top of the CanKit.Pro L2 demux (arc42 §5.3, ADR-5; FR-CO-012). Combines an NMT slave state machine, a local Object Dictionary, an SDO server (for the local OD) and an SDO client (for remote nodes on the same bus), plus the SYNC, EMCY, heartbeat producer/consumer, node-guarding and PDO plumbing of CiA 301 §7.
Implements IDisposable
Remarks¶
One instance represents one CANopen node identity (1..127) on one physical bus, and serves
both roles a CANopen application takes: a device (its own object dictionary, PDOs it
produces and consumes, configured by a master over SDO) and a tool or master (the
SDO client, the NMT master, heartbeat and node-guarding consumers, the SYNC producer).
Profile says which of the two this instance is; the default
of 1F80h follows that profile. Two or more nodes may share the same underlying
ICanBusService so a process-hosted master and one or more
simulated slaves can coexist on a virtual bus.
The object dictionary is the single source of truth for the node's communication
parameters. The methods below that configure a service — StartHeartbeatProducer(TimeSpan),
AddHeartbeatConsumer(byte, TimeSpan), StartSyncProducer(TimeSpan),
ConfigureTpdo(int, PdoMapping, TpdoTransmission, Nullable<uint>, Nullable<TimeSpan>, Nullable<TimeSpan>), ConfigureRpdo(int, PdoMapping, Nullable<uint>, RpdoTransmission) — are writes to the
corresponding CiA 301 objects (1017h, 1016h, 1005h/1006h,
1800h/1A00h, 1400h/1600h), and a value those objects accept from
a master over SDO, or from the application through ObjectDictionary, takes effect
the same way. A value that is not implementable is rejected before it is stored, so the
dictionary never describes behaviour the node does not have.
Disposing.IDisposable.Dispose fails every open transfer with
ObjectDisposedException (on the node's actor: a subscriber that holds the actor
for longer than the actor's five-second shutdown timeout, which is reported through
BackgroundExceptionOccurred, delays that until it returns), stops the producers and starts no further delivery
afterwards (a subscriber that is running when the disposal finishes is not interrupted). It
blocks for up to two seconds on the node's reader and event pump to let them finish;
DisposeAsync(this ICanOpenNode) waits for the same without
holding a thread. Either may be called from a subscriber of this node, whichever thread it runs
on (an event, ApplicationReset, BackgroundExceptionOccurred): the task that thread
belongs to is then not waited for, and it ends when the subscriber returns.
Properties¶
ICanOpenNode.ActiveFlyingMasterNodeId Property¶
Node-id of the active NMT master, once one is known: this node's own id when FlyingMasterRole is Active.
Property Value¶
ICanOpenNode.ActiveFlyingMasterPriority Property¶
Priority level (0 highest, 2 lowest) of ActiveFlyingMasterNodeId.
Property Value¶
ICanOpenNode.DeviceDescription Property¶
What the device description the node was opened with produced — the entries loaded and everything the node could not take as written — or null when the node was opened without one and carries the built-in CiA 301 defaults.
Property Value¶
ICanOpenNode.FlyingMasterRole Property¶
Role in the flying-master election. Inactive
until StartFlyingMaster(ushort, TimeSpan) or until bits 0 and 5 of 1F80h are set.
Property Value¶
ICanOpenNode.NodeId Property¶
Node identifier (1..127) this instance answers as on the bus. 0xFF while
an LSS slave has no active node-id yet (CiA 305): nothing on the bus is addressed with it.
Property Value¶
ICanOpenNode.ObjectDictionary Property¶
The local Object Dictionary (FR-CO-001). Shared by SDO server, PDO mapping and application
code. Created with the communication-profile objects CiA 301 requires of a device that
supports SDO, PDO, SYNC, EMCY, heartbeat and guarding (1000h, 1001h,
1005h, 1006h, 100Ch, 100Dh, 1010h, 1011h,
1014h, 1016h, 1017h, 1018h, 1200h, and per PDO up to
PdoCount the records 1400h/1600h/1800h/
1A00h + n − 1 — 1400h–1403h, 1600h–1603h,
1800h–1803h, 1A00h–1A03h for the default four), each at its
CiA 301 default. 1000h and 1018h carry placeholder values (device type 0,
vendor-id 0 = "no vendor-id assigned") that the application replaces with its own; the
remaining objects are managed by the node and take values, not re-declarations.
Property Value¶
ICanOpenNode.Options Property¶
Options this node was constructed with.
Property Value¶
ICanOpenNode.State Property¶
Current NMT slave state of this node.
Property Value¶
Methods¶
ICanOpenNode.AddHeartbeatConsumer(byte, TimeSpan) Method¶
Registers (or replaces) a heartbeat consumer for
producerNodeId in a free sub-index of 1016h (consumer heartbeat
time; the array grows as consumers are added): if no heartbeat is received within
timeout (1..65535 ms), the node raises HeartbeatTimeout.
The timeout is armed immediately, so a producer that never appears is reported too.
Parameters¶
producerNodeId Byte
timeout TimeSpan
ICanOpenNode.BindPeerDeviceDescription(byte, CanOpenDeviceDescription) Method¶
Binds the EDS or DCF of remote node nodeId. Client SDO transfers to that node then proceed only for (index, sub-index) pairs the description declares (Contains(ushort, byte)). Replaces a description already bound for the same node-id. The description is read at the start of each transfer, without synchronization against an edit of the bound instance in place (Objects): edit it only while no call that reads it is running, or bind another one.
void BindPeerDeviceDescription(byte nodeId, CanKit.Pro.CANopen.CanOpenDeviceDescription description);
Parameters¶
nodeId Byte
description CanOpenDeviceDescription
Exceptions¶
ArgumentException
description is a DCF whose commissioned node-id is not
nodeId. An EDS has no commissioned node-id and may be bound to any node.
A rejected bind leaves the description already stored for that node in place.
Remarks¶
Without a description bound for the server, SdoUploadAsync(byte, ushort, byte, SdoTransferMode, CancellationToken)
and SdoDownloadAsync(byte, ushort, byte, ReadOnlyMemory<byte>, SdoTransferMode, CancellationToken)
transfer only 1000h:00, 1001h:00 and 1018h:00–04
(IsAllowedWithoutPeerDescription(ushort, byte)). Once a description
is bound, those objects are allowed only when the file lists them. A refused transfer
throws PeerSdoAccessException before any frame is sent.
ICanOpenNode.ConfigureRpdo(int, PdoMapping, Nullable<uint>, RpdoTransmission) Method¶
Configures (or replaces) RPDO pdoIndex (1..PdoCount) by writing its
communication record 1400h + n − 1 and mapping record 1600h + n − 1. Incoming
frames matching the COB-ID unpack into the local OD and raise RpdoReceived —
immediately, or with the next SYNC for Synchronous.
cobId is the 1400h:01 word (bit 31 set = configured but disabled;
bit 29 selects an extended CAN frame; bit 30, the RTR bit of a TPDO, has no meaning for an
RPDO and is accepted and ignored); the CAN-ID must not be one CiA 301 §7.3.5 restricts.
The writes are one transaction on the actor loop, as for ConfigureTpdo(int, PdoMapping, TpdoTransmission, Nullable<uint>, Nullable<TimeSpan>, Nullable<TimeSpan>).
void ConfigureRpdo(int pdoIndex, CanKit.Pro.CANopen.Pdo.PdoMapping mapping, System.Nullable<uint> cobId=null, CanKit.Pro.CANopen.Pdo.RpdoTransmission transmission=CanKit.Pro.CANopen.Pdo.RpdoTransmission.EventDriven);
Parameters¶
pdoIndex Int32
mapping PdoMapping
transmission RpdoTransmission
Exceptions¶
ArgumentException
A value was rejected; see ConfigureTpdo(int, PdoMapping, TpdoTransmission, Nullable<uint>, Nullable<TimeSpan>, Nullable<TimeSpan>).
ICanOpenNode.ConfigureTpdo(int, PdoMapping, TpdoTransmission, Nullable<uint>, Nullable<TimeSpan>, Nullable<TimeSpan>) Method¶
Configures (or replaces) TPDO pdoIndex (1..PdoCount) by writing its
communication record 1800h + n − 1 and mapping record 1A00h + n − 1, in the
CiA 301 §7.5.2.38 re-mapping order (PDO invalidated, mapping rewritten, parameters set,
PDO validated). Values not provided use CiA 301 defaults: the COB-ID is the pre-defined
connection set entry, the inhibit time is 0 (off), and the event timer is
DefaultTpdoEventTimerInterval for
EventTimer and 0 otherwise. The writes are one transaction
on the node's actor loop and under the dictionary's write gate: the method returns with
the configuration applied, and neither another caller, nor an SDO download, nor a direct
dictionary write interleaves with the sequence.
void ConfigureTpdo(int pdoIndex, CanKit.Pro.CANopen.Pdo.PdoMapping mapping, CanKit.Pro.CANopen.Pdo.TpdoTransmission transmission=CanKit.Pro.CANopen.Pdo.TpdoTransmission.EventDriven, System.Nullable<uint> cobId=null, System.Nullable<System.TimeSpan> eventTimerInterval=null, System.Nullable<System.TimeSpan> inhibitTime=null);
Parameters¶
pdoIndex Int32
TPDO number 1..CanOpenNodeOptions.PdoCount (or the description's higher count).
mapping PdoMapping
The mapped objects; copied into the mapping record. Every target
must exist in the OD, be PDO-mappable and readable, and have the mapped bit length. A dummy
entry 0001h–0007h (sub-index 0) touches no object but must have its data
type's bit length too (DummyBitLength(ushort)).
transmission TpdoTransmission
Trigger mode; see TpdoTransmission. Cyclic
"every n-th SYNC" is configured by writing the raw byte to 1800h:02 instead.
The 1800h:01 word: a CAN-ID plus the CiA 301 control
bits — bit 31 set configures the PDO but leaves it disabled ("PDO does not exist"), bit 30
set forbids RTR on it. Bit 29 selects a 29-bit CAN-ID; PDOs above 4 require an explicit COB-ID.
eventTimerInterval Nullable<TimeSpan>
Event timer for EventTimer, 1..65535 ms; ignored for the other modes.
inhibitTime Nullable<TimeSpan>
Minimum interval between two transmissions of an event-driven
TPDO (1800h:03, in multiples of 100 µs, at most 6.5535 s). Has no effect on the
synchronous and RTR-only modes, per CiA 301 §7.5.2.37.
Exceptions¶
ArgumentException
A value was rejected; the message names the CiA 301
abort code the same write would have produced over SDO. The PDO is left disabled. Also
thrown, before anything is written, when the PDO is not declared on this node (a bound
description omits its records), or when the bound description declares no inhibit time
(1800h:03) or no event timer (1800h:05) — both optional per CiA 301 Table 71 —
and a non-zero value is requested for the absent one.
ICanOpenNode.GetPeerDeviceDescription(byte) Method¶
The description bound for nodeId, or null.
Parameters¶
nodeId Byte
Returns¶
ICanOpenNode.ObserveForeignPdoAsync(byte, uint, ReadOnlyMemory<byte>, CanOpenDeviceDescription, IForeignPdoSink, CancellationToken) Method¶
Decodes a PDO payload of peerNodeId and writes each mapped object to sink. Nothing is written to this node's object dictionary, and a frame that is not one of this node's own RPDOs is still not applied when it arrives: this method is the only path that splits a peer PDO.
System.Threading.Tasks.Task<CanKit.Pro.CANopen.ForeignPdoObserveResult> ObserveForeignPdoAsync(byte peerNodeId, uint cobId, System.ReadOnlyMemory<byte> payload, CanKit.Pro.CANopen.CanOpenDeviceDescription peerDescription, CanKit.Pro.CANopen.IForeignPdoSink sink, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
peerNodeId Byte
The node whose PDO this payload is (1..127).
cobId UInt32
The observed ID, with bit 29 set for an extended frame.
payload ReadOnlyMemory<Byte>
The PDO data, 0..8 bytes.
peerDescription CanOpenDeviceDescription
EDS or DCF of the peer. Supplies the COB-ID and the mapping when the live read of that record fails.
sink IForeignPdoSink
Where each decoded object is written.
cancellationToken CancellationToken
Cancels an in-flight mapping upload. Cancellation is not a failed read: the file is not used in its place.
Returns¶
Exceptions¶
ArgumentNullException
peerDescription or
sink is null.
ArgumentOutOfRangeException
peerNodeId is outside
1..127, cobId is not a valid base or extended PDO key, or payload is
longer than 8 bytes.
Remarks¶
Which PDO the COB-ID belongs to is read live from 1400h:01 / 1800h:01 when a
peer description bound for peerNodeId declares the record; without a
binding the peer-SDO gate refuses every PDO record before a frame is sent, and the whole
observation is decoded from peerDescription. A
value that comes back is used ahead of peerDescription, including a PDO
the device marks invalid (bit 31 set) or a CAN-ID the file does not name. The same entry
in the file ($NODEID resolved to peerNodeId) is used only when
that upload aborts, times out, is refused by the peer-SDO gate, or does not return a word.
A CAN-ID CiA 301 §7.3.5 restricts is not accepted from either source. Observations of one
peer are serialized, so two of them do not fail each other on the one-transfer-per-server
limit.
The live reads of one observation are one snapshot of the peer: the peer's SDO channel is taken without waiting and held to the end, so a safety transaction that starts meanwhile waits for it and another SDO call of this node to that peer is refused as in flight. A channel busy at the start — a call in flight, a safety transaction — makes every live read of that observation "already in flight", and the whole snapshot is the file's; a live COB-ID is never combined with the file's mapping because a caller came in between.
The mapping is the live record 1600h–17FFh or 1A00h–1BFFh,
uploaded over the same SDO client. A pair the bound peer description does not allow is
refused before a frame is sent and is a failed live read. An upload that aborts or times
out, or an invalid mapping exceeding 64 bits, makes the live record unavailable and the
mapping in the file is used instead. Mapping counts FEh/FFh decode an MPDO multiplexer.
A record neither the device nor the file can supply is not decoded.
The split follows the same length rule as an RPDO this node consumes: fewer bytes than
the mapping writes nothing; extra bytes are ignored; a dummy entry 0001h–0007h
consumes its bits and writes no signal.
ICanOpenNode.RemoveHeartbeatConsumer(byte) Method¶
Removes a previously-registered heartbeat consumer for
producerNodeId (clears its 1016h entry). No-op if none was
registered.
Parameters¶
producerNodeId Byte
ICanOpenNode.RestoreDefaultParameters() Method¶
Marks the stored power-on values for discarding: the next NMT reset restores the CiA 301
defaults the node was created with (the local equivalent of a master writing "load" to
1011h:01; per §7.5.2.14 the defaults become valid with the reset, not before).
ICanOpenNode.SdoDownloadAsync(byte, ushort, byte, ReadOnlyMemory<byte>, SdoTransferMode, CancellationToken) Method¶
Writes an object to serverNodeId's OD. Auto selects the transport from the data length: at or above SdoBlockThresholdBytes block transfer, and below it the CiA 301 split — 1..4 bytes expedited, an empty value and 5 bytes and up segmented (the expedited encoding cannot express 0 bytes). The threshold is checked first, so it also decides the expedited range: a threshold of 1..4 (which the options permit) sends a short payload by block transfer rather than expedited. Pass Block to force block transfer below that threshold; the expedited/segmented split itself is dictated by CiA 301 and is not selectable. Refused locally with PeerSdoAccessException when the pair is not allowed for serverNodeId; see BindPeerDeviceDescription(byte, CanOpenDeviceDescription). One transfer per server is in flight at a time: with one in flight — a safety transaction with that server counts as one for its whole length — the call fails with InvalidOperationException before anything is sent.
System.Threading.Tasks.Task SdoDownloadAsync(byte serverNodeId, ushort index, byte subindex, System.ReadOnlyMemory<byte> data, CanKit.Pro.CANopen.Sdo.SdoTransferMode mode=CanKit.Pro.CANopen.Sdo.SdoTransferMode.Auto, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
serverNodeId Byte
index UInt16
subindex Byte
data ReadOnlyMemory<Byte>
mode SdoTransferMode
cancellationToken CancellationToken
Returns¶
Remarks¶
Not gated by this node's NMT state, as SdoUploadAsync(byte, ushort, byte, SdoTransferMode, CancellationToken).
Cancelling cancellationToken ends the returned task as cancelled and
sends the server an abort (0800 0000h). During a block download the sub-block
being sent stops before its next segment, but the segment it had already started to hand to
the bus is not recalled: it can reach the bus after the abort, and after the initiate of a
transfer to the same server started right after the cancellation (#377). The task does not
wait for the abort to be on the wire.
ICanOpenNode.SdoDownloadAsync(byte, ushort, byte, ReadOnlyMemory<byte>, CancellationToken) Method¶
Writes an object to serverNodeId's OD using Auto. Source-compatible overload for callers that pass a positional CancellationToken after data.
System.Threading.Tasks.Task SdoDownloadAsync(byte serverNodeId, ushort index, byte subindex, System.ReadOnlyMemory<byte> data, System.Threading.CancellationToken cancellationToken);
Parameters¶
serverNodeId Byte
index UInt16
subindex Byte
data ReadOnlyMemory<Byte>
cancellationToken CancellationToken
Returns¶
ICanOpenNode.SdoUploadAsync(byte, ushort, byte, SdoTransferMode, CancellationToken) Method¶
Reads an object from serverNodeId's OD. Auto uses the classic client because the payload length is unknown until the server replies — whether that reply is expedited or segmented is the server's choice and is handled transparently. Pass Block to force block transfer (CiA 301 §7.2.4.3.12–7.2.4.3.15). (FR-CO-002 / FR-CO-003 / FR-CO-004). Refused locally with PeerSdoAccessException when the pair is not allowed for serverNodeId; see BindPeerDeviceDescription(byte, CanOpenDeviceDescription). One transfer per server is in flight at a time: with one in flight — a safety transaction with that server counts as one for its whole length — the call fails with InvalidOperationException before anything is sent.
System.Threading.Tasks.Task<byte[]> SdoUploadAsync(byte serverNodeId, ushort index, byte subindex, CanKit.Pro.CANopen.Sdo.SdoTransferMode mode=CanKit.Pro.CANopen.Sdo.SdoTransferMode.Auto, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
serverNodeId Byte
index UInt16
subindex Byte
mode SdoTransferMode
cancellationToken CancellationToken
Returns¶
Remarks¶
The client is not gated by this node's NMT state: it transfers in Stopped too, as SendSyncAsync(CancellationToken) sends (#254). What CiA 301 Table 37 rules out in Stopped is applied to this node's SDO server.
ICanOpenNode.SdoUploadAsync(byte, ushort, byte, CancellationToken) Method¶
Reads an object from serverNodeId's OD using Auto (the server's initiate response decides expedited vs. segmented; the size is unknown up front so Auto does not select block upload — pass Block explicitly). Source-compatible overload for callers that pass a positional CancellationToken.
System.Threading.Tasks.Task<byte[]> SdoUploadAsync(byte serverNodeId, ushort index, byte subindex, System.Threading.CancellationToken cancellationToken);
Parameters¶
serverNodeId Byte
index UInt16
subindex Byte
cancellationToken CancellationToken
Returns¶
ICanOpenNode.SendEmcyAsync(ushort, byte, ReadOnlyMemory<byte>, CancellationToken) Method¶
Transmits an EMCY frame from this node on the COB-ID configured in 1014h, after
writing errorRegister to 1001h so the error register a master
reads over SDO is the one the last EMCY carried: the write and the transmission are one
ordered step on the node's actor loop, and every EMCY of this node goes out through one
ordered path, so overlapping calls reach the bus in the order the register was written.
In NMT state Stopped the EMCY is held and the most recent one is transmitted when the
node leaves Stopped (CiA 301 §7.3.2.2.4). The returned task faults with
InvalidOperationException when EMCY is disabled (bit 31 of 1014h set).
System.Threading.Tasks.Task SendEmcyAsync(ushort errorCode, byte errorRegister, System.ReadOnlyMemory<byte> manufacturerSpecific=default(System.ReadOnlyMemory<byte>), System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
errorCode UInt16
errorRegister Byte
manufacturerSpecific ReadOnlyMemory<Byte>
cancellationToken CancellationToken
Returns¶
ICanOpenNode.SendNmtCommandAsync(NmtCommand, byte, CancellationToken) Method¶
Sends an NMT master command (COB-ID 0x000). targetNodeId
zero means broadcast to all nodes. This method only transmits the command and does not
apply it to the local node. Whether the node obeys it anyway depends on the adapter: one
that delivers the node's own transmits back (a loopback, or hardware in an echo mode) hands
it to the receive path, where it is applied via NmtCommandReceived; one that
does not (Normal mode on a non-echoing adapter) leaves the node's own NMT state alone, which
then follows the boot-up of an active flying master (bit 2 of 1F80h clear) or another
master. Do not rely on either.
System.Threading.Tasks.Task SendNmtCommandAsync(CanKit.Pro.CANopen.Nmt.NmtCommand command, byte targetNodeId, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
command NmtCommand
targetNodeId Byte
cancellationToken CancellationToken
Returns¶
ICanOpenNode.SendSyncAsync(CancellationToken) Method¶
Transmits a single SYNC frame (payload-less) on the SYNC COB-ID configured in
1005h.
System.Threading.Tasks.Task SendSyncAsync(System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
cancellationToken CancellationToken
Returns¶
Remarks¶
This is a raw send, not the producer: it is not gated by the NMT state and not by
bit 30 of 1005h ("device generates SYNC"), so a node in Stopped, or one that is not
configured to produce SYNC, transmits when asked. The periodic producer
(StartSyncProducer(TimeSpan)) is the one that follows CiA 301 Table 37.
ICanOpenNode.StartFlyingMaster(ushort, TimeSpan) Method¶
Joins the NMT flying-master election at priorityLevel (0 highest, 2
lowest). Writes that level to 1F90h:03 and sets bits 0 and 5 of 1F80h.
The first election after this call is a cold boot: if no master answers, the node
broadcasts NMT Reset Communication and runs the election again as a warm boot. That
reset restores power-on values, so this method records 1F80h, 1F81h,
1F89h and 1F90h as power-on values before it starts; call
StoreParameters() first if the rest of the configuration must survive the same
reset. After the node becomes the active master it boots the slaves assigned in
1F81h (see the package README).
Parameters¶
priorityLevel UInt16
0, 1 or 2. Lower wins. Equal priority does not depose an active master; in a timeslot race the lower node-id waits less and claims first.
activeMasterHeartbeatTimeout TimeSpan
While this node stands by, a heartbeat consumer
(1016h) for the active master is installed at this timeout unless one already
exists. A timeout starts a new election. When this node becomes the active master and
1017h is 0, the producer is started at half this timeout so peers can see the loss.
Exceptions¶
ArgumentOutOfRangeException
priorityLevel is above 2,
or activeMasterHeartbeatTimeout is outside 1..65535 ms.
ArgumentException
1F90h:04 is not greater than 127 times
1F90h:05, so the timeslots would not keep a better priority ahead of a worse one.
ICanOpenNode.StartHeartbeatProducer(TimeSpan) Method¶
Starts (or replaces) the local heartbeat producer with
interval: writes 1017h (producer heartbeat time, 1..65535 ms).
While the producer is active the node uses the heartbeat protocol and does not answer
node-guarding RTRs (CiA 301 §7.2.8.3.2.2).
Parameters¶
interval TimeSpan
ICanOpenNode.StartNodeGuardingConsumer(byte, TimeSpan, byte) Method¶
Starts the node-guarding consumer for producerNodeId: sends an RTR
on 0x700 + producerNodeId every guardTime and expects the peer
to reply with a one-byte data frame (toggle bit in bit 7, NMT state in bits 0..6). If
guardTime × lifeTimeFactor elapses without a valid response the node raises
NodeGuardingTimeout. Replaces any existing consumer for the same peer.
void StartNodeGuardingConsumer(byte producerNodeId, System.TimeSpan guardTime, byte lifeTimeFactor);
Parameters¶
producerNodeId Byte
guardTime TimeSpan
lifeTimeFactor Byte
ICanOpenNode.StartSyncProducer(TimeSpan) Method¶
Starts a periodic SYNC producer with the given interval: writes 1006h
(communication cycle period, in µs) and sets bit 30 of 1005h ("device generates
SYNC"). SYNC is not transmitted in NMT state Stopped (CiA 301 Table 37).
Parameters¶
interval TimeSpan
ICanOpenNode.StopFlyingMaster() Method¶
Leaves the election: clears bits 0 and 5 of 1F80h and drops a heartbeat
consumer this node installed for the active master. Recorded as the power-on value of
1F80h, so a later reset does not rejoin.
ICanOpenNode.StopHeartbeatProducer() Method¶
Stops the local heartbeat producer: writes 1017h = 0.
ICanOpenNode.StopNodeGuardingConsumer(byte) Method¶
Stops the node-guarding consumer for producerNodeId. No-op when none is running.
Parameters¶
producerNodeId Byte
ICanOpenNode.StopSyncProducer() Method¶
Stops the periodic SYNC producer: clears bit 30 of 1005h.
ICanOpenNode.StoreParameters() Method¶
Takes the current values of the node's communication-profile objects as the power-on
values an NMT reset restores — the local equivalent of a master writing "save" to
1010h:01. Without a store, a reset restores the CiA 301 defaults the node was
created with, so a device configured through ConfigureTpdo(int, PdoMapping, TpdoTransmission, Nullable<uint>, Nullable<TimeSpan>, Nullable<TimeSpan>) /
ConfigureRpdo(int, PdoMapping, Nullable<uint>, RpdoTransmission) calls this once its configuration is complete.
ICanOpenNode.TriggerTpdoAsync(int, CancellationToken) Method¶
Requests a TPDO transmission from the application (CiA 301 "internal event").
Event-driven TPDOs (FEh/FFh) transmit subject to their inhibit time; a
synchronous-acyclic TPDO (00h) transmits after the next SYNC. The other types do
not react to an event, so the call sends nothing for them: a cyclic TPDO
(01h–F0h) is transmitted by the SYNC, and an RTR-only TPDO
(FCh/FDh) by an RTR. The node still respects the current NMT state (only
fires in Operational); a call that sends nothing completes
normally, as for a PDO that is not valid.
System.Threading.Tasks.Task TriggerTpdoAsync(int pdoIndex, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
pdoIndex Int32
cancellationToken CancellationToken
Returns¶
ICanOpenNode.UnbindPeerDeviceDescription(byte) Method¶
Drops the description bound for nodeId. No-op when none is bound. Afterwards the mandatory-object exemption applies to that node again.
Parameters¶
nodeId Byte
Events¶
ICanOpenNode.ApplicationReset Event¶
Raised synchronously on the actor loop during an NMT Reset Node or Reset Communication, after the communication-profile objects have been restored and before the boot-up is transmitted: the application restores its own object dictionary objects in the handler, and the node announces itself only when the handler has returned — a master reacting to the boot-up never reads a value the reset had not reached. When layer setting services are on, the pending node-id is already the active one and the pre-defined COB-IDs already name it. The handler runs on the loop the node's own work runs on, so it must not wait for the node (an SDO transfer, StoreParameters(), a configuration method); its exception is reported through BackgroundExceptionOccurred and does not stop the reset.
Event Type¶
EventHandler<NmtResetEventArgs>
ICanOpenNode.BackgroundExceptionOccurred Event¶
Raised on background exceptions from the actor loop / subscription reader.
Raised on a thread-pool thread, never on the node's actor loop or its event pump, so a handler may wait on the node -- an SDO transfer, StoreParameters(), a configuration method, IDisposable.Dispose -- without deadlocking the actor (#356). Reports are delivered one at a time, in the order they were made; a handler that blocks holds up the reports behind it, not the node. Each handler is called on its own, so one that throws does not keep the report from the handlers after it; its exception is dropped. A failure that happens once the disposal has finished is not reported; one that happened before may reach its handlers after IDisposable.Dispose has returned. A handler that disposes the node ends that report's round: the handlers after it are not called, unless the node was already disposed when the round began.
Event Type¶
ICanOpenNode.EmcyReceived Event¶
Raised when an EMCY frame is received on the bus (FR-CO-011). Not discarded
when the event queue is over EventQueueCapacity. While a
handler is behind, an EMCY identical to one still waiting (same producer, code, register
and manufacturer field) is folded into it, unless another event about that producer was
queued in between, and a producer with
EventQueueCapacity distinct emergencies already waiting
has its further ones discarded, reported once per burst on
BackgroundExceptionOccurred. The producer is the COB-ID minus 080h,
the pre-defined connection set: for a peer whose 1014h was moved off that set,
ProducerNodeId is not the peer's node-id, and the folding above
is keyed on it as well. An EMCY frame shorter than eight bytes (CiA 301 §7.2.7.3.1) raises
no event: it is dropped, not padded, and the first one from each producer is reported on
BackgroundExceptionOccurred as a CanOpenTransportException;
later ones from that producer are dropped without a report.
Event Type¶
EventHandler<EmcyReceivedEventArgs>
ICanOpenNode.FlyingMasterChanged Event¶
Raised when this node becomes the active master, yields, forces a new election, loses the active master, sees an inconsistent claim, or times out a mandatory slave.
Event Type¶
EventHandler<FlyingMasterChangedEventArgs>
ICanOpenNode.HeartbeatReceived Event¶
Raised when a heartbeat or bootup frame is received from any node. Data frames on
0x700 + node-id are heartbeats; a node-guarding response is reported through
NodeGuardingReceived instead when a guarding consumer is registered for the
producer.
Event Type¶
EventHandler<HeartbeatReceivedEventArgs>
ICanOpenNode.HeartbeatTimeout Event¶
Raised when a configured heartbeat consumer detects a missing heartbeat. Not discarded when the event queue is over EventQueueCapacity — losing it would leave the peer looking alive. While a timeout for the same producer is still waiting for the handler, a further one is folded into it rather than queued again, unless a heartbeat from that producer was queued in between. The event that waits then reports the newest settings.
Event Type¶
EventHandler<HeartbeatTimeoutEventArgs>
ICanOpenNode.LifeGuardingEvent Event¶
Producer-side life guarding (CiA 301 §7.2.8.2.2.2 / §7.2.8.3.2.1): raised with
Occurred when this node, being guarded by a master, was
not polled within its node life time (100Ch guard time × 100Dh life time
factor, both from the object dictionary), and with Resolved
when a poll arrives again afterwards. Guarding starts with the first RTR the node answers;
both objects at 0 (the default) disable it, and so does an RTR the node does not answer --
with the heartbeat producer on, or with RespondToNodeGuardingRtr
off.
Event Type¶
EventHandler<LifeGuardingEventArgs>
ICanOpenNode.NmtCommandReceived Event¶
Raised for every NMT master command whose target matches this node (or the broadcast target 0) and which the node applies. Delivered on the node's event queue, after the node has acted on the command — for a reset, possibly after the boot-up is on the bus; to restore application objects before that, use ApplicationReset. While this node is the active flying master it ignores a command addressed to its own node-id, and it does not apply a broadcast reset or stop to itself.
Event Type¶
EventHandler<NmtCommandReceivedEventArgs>
ICanOpenNode.NodeGuardingReceived Event¶
Raised whenever a node-guarding response (data frame on 0x700 + producer
with the toggle bit in bit 7 and the NMT state in bits 0..6) is received for a
configured node-guarding consumer (FR-CO-009 / CiA 301 §7.2.8.3.2.1). A response whose
toggle bit repeats the previous one is "handled as if it was not received"
(§7.2.8.3.2.1): it raises no event and does not re-arm the life time, so a producer that
stops alternating is reported through NodeGuardingTimeout.
Event Type¶
EventHandler<NodeGuardingReceivedEventArgs>
ICanOpenNode.NodeGuardingTimeout Event¶
Raised when a configured node-guarding consumer's life-time
(guardTime × lifeTimeFactor) elapses without seeing an answer to the RTR poll
(FR-CO-009). Not discarded when the event queue is over
EventQueueCapacity — losing it would leave the peer
looking alive. While a timeout for the same producer is still waiting for the handler,
a further one is folded into it rather than queued again, unless a guarding response from
that producer was queued in between. The event that waits then reports the newest settings.
Event Type¶
EventHandler<NodeGuardingTimeoutEventArgs>
ICanOpenNode.RpdoReceived Event¶
Raised after an RPDO the local node has mapped is received and unpacked into the OD — immediately for an event-driven RPDO, with the next SYNC for a synchronous one.
Event Type¶
EventHandler<RpdoReceivedEventArgs>
ICanOpenNode.SyncReceived Event¶
Raised whenever a SYNC frame is received on the configured SYNC COB-ID
(1005h), either from a remote producer or from this node's own producer if echo is
on. Not raised in NMT state Stopped, where SYNC is not active (CiA 301 Table 37).