IJ1939TpChannel Interface¶
One J1939-TP channel bound to a single J1939 source address on one physical bus. It carries both TP.BAM (broadcast) and TP.CM (connection-mode) sessions in parallel, each in its own actor-owned state (SRS FR-TP-034/035) so multiple concurrent peers do not interfere.
Implements IDisposable
Remarks¶
Threading model (SRS FR-TP-034 = FR-TP-016/017 applied to J1939-TP): every session's state (sequence numbers, remaining bytes, block counters, T1..T4 deadlines and the BAM packet spacing) lives inside a single IProtocolActor mailbox and is only ever read/written on the actor's loop thread. Callers may invoke SendBamAsync(uint, ReadOnlyMemory<byte>, CancellationToken) or SendCmAsync(uint, byte, ReadOnlyMemory<byte>, CancellationToken) concurrently from any thread; the channel serializes them per destination address, so one PDU at a time is on the wire towards any one destination — and, since every BAM goes to the global address, one BAM at a time per channel (J1939-21 §5.10.3). A send whose destination is busy waits its turn, at most MaxQueuedSendsPerDestination of them per destination, counting sends the channel has accepted but not yet started: one more faults at the call with J1939TpSendRejectedException. There is no deadline on the wait -- a peer may legitimately hold the session ahead (J1939-21 §5.10.2.4, CTS(0)) -- so the caller's CancellationToken is what bounds it, and a cancelled send leaves the queue at once. A second send for the same (destination, PGN) while one is in flight or waiting faults with InvalidOperationException.
Received PDUs are delivered both as an event (DatagramReceived) and via ReceiveAsync(CancellationToken) / ReceiveAllAsync(CancellationToken). Both surfaces share the same bounded buffer; if it fills, the oldest datagram is dropped so the RX pipeline never stalls the actor.
IDisposable.Dispose is thread-safe and idempotent (FR-RAW-021).
Properties¶
IJ1939TpChannel.Options Property¶
Options captured at construction time (immutable).
Property Value¶
IJ1939TpChannel.SourceAddress Property¶
The J1939 source address this channel identifies itself as on the bus.
Property Value¶
Methods¶
IJ1939TpChannel.ReceiveAllAsync(CancellationToken) Method¶
Enumerates every reassembled inbound datagram until the channel is disposed. A reassembly abort is thrown out of the enumeration as J1939TpAbortException, the fault ReceiveAsync(CancellationToken) reports, and it <em>ends</em> that enumeration. The channel and its buffer stay open: datagrams that arrive after the abort wait for the next receive, so a caller that keeps receiving catches the exception and enumerates again -- as a J1939 node does with its own channel (#195, #356). Each abort is delivered to one waiter only.
System.Collections.Generic.IAsyncEnumerable<CanKit.Pro.J1939Tp.J1939TpDatagram> ReceiveAllAsync(System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
cancellationToken CancellationToken
Returns¶
IAsyncEnumerable<J1939TpDatagram>
IJ1939TpChannel.ReceiveAsync(CancellationToken) Method¶
Awaits the next fully reassembled inbound TP.BAM or TP.CM datagram, or faults with J1939TpAbortException when an in-flight reassembly is aborted (bad TP.DT sequence number, T1/T2 timeout, peer Connection Abort, or a new BAM from the same source replacing one still in progress — J1939-21 §5.10.3). One waiter consumes the fault; subsequent receives remain available for later successful datagrams.
System.Threading.Tasks.Task<CanKit.Pro.J1939Tp.J1939TpDatagram> ReceiveAsync(System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
cancellationToken CancellationToken
Returns¶
IJ1939TpChannel.SendBamAsync(uint, ReadOnlyMemory<byte>, CancellationToken) Method¶
Broadcasts payload as one TP.BAM session (FR-TP-030). The task completes when the last TP.DT frame is TX-confirmed by the driver. Payload length must be in [9, 1785] bytes (J1939-21 §5.10.1: TP is only used above 8 bytes).
System.Threading.Tasks.Task SendBamAsync(uint pgn, System.ReadOnlyMemory<byte> payload, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
pgn UInt32
Data PGN of the multi-packet message being announced.
payload ReadOnlyMemory<Byte>
User payload; 9..1785 bytes.
cancellationToken CancellationToken
Standard .NET cancellation of the returned task; also removes a send still waiting for its slot.
Returns¶
Exceptions¶
ArgumentOutOfRangeException
Thrown by the call itself: pgn does not fit in 18 bits or is a PDU1 PGN
with a low byte other than 0, or the payload length is outside [9, 1785].
ObjectDisposedException
Thrown by the call itself when the channel is already disposed; reported through the
returned task when it is disposed while the send is pending, or when a J1939 node that owns
the channel no longer holds its source address by the time the session would start.
InvalidOperationException
Reported through the returned task, already faulted when the call returns, when a send for
the same PGN is still pending.
J1939TpSendRejectedException
Reported through the returned task, already faulted when the call returns, when the
destination has its one send on the wire and
MaxQueuedSendsPerDestination more pending (waiting or handed
to the channel and not yet started); later, when the CAN driver rejects one of the
session's frames.
J1939TpException
Reported through the returned task when a frame's transmit confirmation fails otherwise
(bus-off, confirmation timeout).
OperationCanceledException
Reported through the returned task when cancellationToken is cancelled
before the last TP.DT is confirmed.
IJ1939TpChannel.SendCmAsync(uint, byte, ReadOnlyMemory<byte>, CancellationToken) Method¶
Sends payload as one TP.CM session to destinationAddress (FR-TP-031). The task completes when the peer's EndOfMsgAck arrives (or faults with J1939TpAbortException on abort/timeout).
System.Threading.Tasks.Task SendCmAsync(uint pgn, byte destinationAddress, System.ReadOnlyMemory<byte> payload, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));
Parameters¶
pgn UInt32
Data PGN of the multi-packet message being sent.
destinationAddress Byte
Target node's source address (must not be 0xFF nor this channel's own SourceAddress).
payload ReadOnlyMemory<Byte>
User payload; 9..1785 bytes.
cancellationToken CancellationToken
Standard .NET cancellation of the returned task; also removes a send still waiting for its slot.
Returns¶
Exceptions¶
ArgumentOutOfRangeException
Thrown by the call itself: destinationAddress is 0xFF or this channel's
own SourceAddress, pgn does not fit in 18 bits or is a
PDU1 PGN with a low byte other than 0, or the payload length is outside [9, 1785].
ObjectDisposedException
Thrown by the call itself when the channel is already disposed; reported through the
returned task when it is disposed while the send is pending, or when a J1939 node that owns
the channel no longer holds its source address by the time the session would start.
InvalidOperationException
Reported through the returned task, already faulted when the call returns, when a send to
the same destination with the same PGN is still pending.
J1939TpSendRejectedException
Reported through the returned task, already faulted when the call returns, when the
destination has its one send on the wire and
MaxQueuedSendsPerDestination more pending (waiting or handed
to the channel and not yet started); later, when the CAN driver rejects one of the
session's frames.
J1939TpAbortException
Reported through the returned task when the session is aborted: by the peer's Connection
Abort, by T3 or T4 expiring, or by this side on a protocol error in the peer's answers.
J1939TpException
Reported through the returned task when a frame's transmit confirmation fails otherwise
(bus-off, confirmation timeout).
OperationCanceledException
Reported through the returned task when cancellationToken is cancelled
before the EndOfMsgAck arrives; a session already opened with the peer is aborted on the
wire.
Events¶
IJ1939TpChannel.BackgroundExceptionOccurred Event¶
Raised when a background failure (session timeout on an idle receiver, event-handler exception, subscription failure, actor loop exception) must be surfaced to the application. Failures tied to a specific SendBamAsync(uint, ReadOnlyMemory<byte>, CancellationToken) / SendCmAsync(uint, byte, ReadOnlyMemory<byte>, CancellationToken) call are reported via that call's returned task.
Raised on a thread-pool thread, never on the channel's actor loop, and only once what the report announces is in place: a reassembly abort has already faulted the inbox, so a handler that answers it with ReceiveAsync(CancellationToken) -- or waits on a send, or disposes the channel -- gets the fault rather than 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 channel. 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 report may reach its handlers after IDisposable.Dispose has returned.
Event Type¶
IJ1939TpChannel.DatagramReceived Event¶
Raised every time a full PDU is reassembled, after the datagram has been enqueued for ReceiveAsync(CancellationToken) / ReceiveAllAsync(CancellationToken), and on the thread pool, not on the actor's loop -- so a handler that waits on this channel synchronously gets the datagram rather than deadlocking the actor (#58; as ISO-TP delivers). Two datagrams reassembled close together may therefore reach their handlers concurrently, and not necessarily in the order they completed; ReceiveAsync(CancellationToken) keeps that order. A throwing handler is caught and surfaced via BackgroundExceptionOccurred.