Skip to content

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 and PDO plumbing needed by CiA 301 §7.

public interface ICanOpenNode : System.IDisposable

Implements IDisposable

Remarks

One instance represents one CANopen node identity (1..127) on one physical bus. 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 in tests — that is what the MVP integration tests exercise.

Properties

ICanOpenNode.NodeId Property

Node identifier (1..127) this instance answers as on the bus.

byte NodeId { get; }

Property Value

Byte

ICanOpenNode.ObjectDictionary Property

The local Object Dictionary (FR-CO-001). Shared by SDO server, PDO mapping and application code.

CanKit.Pro.CANopen.ObjectDictionary ObjectDictionary { get; }

Property Value

ObjectDictionary

ICanOpenNode.Options Property

Options this node was constructed with.

CanKit.Pro.CANopen.CanOpenNodeOptions Options { get; }

Property Value

CanOpenNodeOptions

ICanOpenNode.State Property

Current NMT slave state of this node.

CanKit.Pro.CANopen.Nmt.NmtState State { get; }

Property Value

NmtState

Methods

ICanOpenNode.AddHeartbeatConsumer(byte, TimeSpan) Method

Registers (or replaces) a heartbeat consumer for producerNodeId: if no heartbeat is received within timeout, the node raises HeartbeatTimeout.

void AddHeartbeatConsumer(byte producerNodeId, System.TimeSpan timeout);

Parameters

producerNodeId Byte

timeout TimeSpan

ICanOpenNode.ConfigureRpdo(int, PdoMapping, Nullable<uint>) Method

Configures (or replaces) RPDO pdoIndex (1..4). Incoming frames matching the mapping unpack straight into the local OD and raise RpdoReceived.

void ConfigureRpdo(int pdoIndex, CanKit.Pro.CANopen.Pdo.PdoMapping mapping, System.Nullable<uint> cobId=null);

Parameters

pdoIndex Int32

mapping PdoMapping

cobId Nullable<UInt32>

ICanOpenNode.ConfigureTpdo(int, PdoMapping, TpdoTransmission, Nullable<uint>, Nullable<TimeSpan>) Method

Configures (or replaces) TPDO pdoIndex (1..4). Values not provided use CiA 301 defaults: COB-ID is the pre-defined connection set entry and the event timer defaults to DefaultTpdoEventTimerInterval.

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);

Parameters

pdoIndex Int32

mapping PdoMapping

transmission TpdoTransmission

cobId Nullable<UInt32>

eventTimerInterval Nullable<TimeSpan>

ICanOpenNode.RemoveHeartbeatConsumer(byte) Method

Removes a previously-registered heartbeat consumer for producerNodeId. No-op if none was registered.

void RemoveHeartbeatConsumer(byte producerNodeId);

Parameters

producerNodeId Byte

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, 5 bytes and up segmented. 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.

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

Task

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

Task

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.15). (FR-CO-002 / FR-CO-003 / FR-CO-004).

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

Task<Byte[]>

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

Task<Byte[]>

ICanOpenNode.SendEmcyAsync(ushort, byte, ReadOnlyMemory<byte>, CancellationToken) Method

Transmits an EMCY frame from this node.

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

Task

ICanOpenNode.SendNmtCommandAsync(NmtCommand, byte, CancellationToken) Method

Sends an NMT master command (COB-ID 0x000). targetNodeId zero means broadcast to all nodes. Applying the command to the local node (either broadcast or targeting this node's own id) is expected to be handled by the receiver via NmtCommandReceived.

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

Task

ICanOpenNode.SendSyncAsync(CancellationToken) Method

Transmits a single SYNC frame (payload-less).

System.Threading.Tasks.Task SendSyncAsync(System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));

Parameters

cancellationToken CancellationToken

Returns

Task

ICanOpenNode.StartHeartbeatProducer(TimeSpan) Method

Starts (or replaces) the local heartbeat producer with interval.

void StartHeartbeatProducer(System.TimeSpan interval);

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.

void StartSyncProducer(System.TimeSpan interval);

Parameters

interval TimeSpan

ICanOpenNode.StopHeartbeatProducer() Method

Stops the local heartbeat producer.

void StopHeartbeatProducer();

ICanOpenNode.StopNodeGuardingConsumer(byte) Method

Stops the node-guarding consumer for producerNodeId. No-op when none is running.

void StopNodeGuardingConsumer(byte producerNodeId);

Parameters

producerNodeId Byte

ICanOpenNode.StopSyncProducer() Method

Stops the periodic SYNC producer.

void StopSyncProducer();

ICanOpenNode.TriggerTpdoAsync(int, CancellationToken) Method

Manually triggers a TPDO transmission. The node still respects the current NMT state (only fires when the node is in Operational).

System.Threading.Tasks.Task TriggerTpdoAsync(int pdoIndex, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));

Parameters

pdoIndex Int32

cancellationToken CancellationToken

Returns

Task

Events

ICanOpenNode.BackgroundExceptionOccurred Event

Raised on background exceptions from the actor loop / subscription reader.

event EventHandler<Exception>? BackgroundExceptionOccurred;

Event Type

EventHandler<Exception>

ICanOpenNode.EmcyReceived Event

Raised when an EMCY frame is received on the bus (FR-CO-011).

event EventHandler<EmcyReceivedEventArgs>? EmcyReceived;

Event Type

EventHandler<EmcyReceivedEventArgs>

ICanOpenNode.HeartbeatReceived Event

Raised when a heartbeat (or bootup) frame is received for any node the local consumer subscribed to.

event EventHandler<HeartbeatReceivedEventArgs>? HeartbeatReceived;

Event Type

EventHandler<HeartbeatReceivedEventArgs>

ICanOpenNode.HeartbeatTimeout Event

Raised when a configured heartbeat consumer detects a missing heartbeat.

event EventHandler<HeartbeatTimeoutEventArgs>? HeartbeatTimeout;

Event Type

EventHandler<HeartbeatTimeoutEventArgs>

ICanOpenNode.NmtCommandReceived Event

Raised on the actor loop for every NMT master command whose target matches this node (or the broadcast target 0).

event EventHandler<NmtCommandReceivedEventArgs>? NmtCommandReceived;

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.3).

event EventHandler<NodeGuardingReceivedEventArgs>? NodeGuardingReceived;

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).

event EventHandler<NodeGuardingTimeoutEventArgs>? NodeGuardingTimeout;

Event Type

EventHandler<NodeGuardingTimeoutEventArgs>

ICanOpenNode.RpdoReceived Event

Raised after an RPDO the local node has mapped is received and unpacked into the OD.

event EventHandler<RpdoReceivedEventArgs>? RpdoReceived;

Event Type

EventHandler<RpdoReceivedEventArgs>

ICanOpenNode.SyncReceived Event

Raised whenever a SYNC frame is received (either from a remote producer or from this node's own producer if echo is on).

event EventHandler<SyncReceivedEventArgs>? SyncReceived;

Event Type

EventHandler<SyncReceivedEventArgs>