ISO-TP Annotator

CanKing service extension that decodes and annotates ISO-TP (ISO 15765-2) traffic on CAN and CAN-FD buses.

The extension observes incoming frames, recognizes the four ISO-TP frame types (Single Frame, First Frame, Consecutive Frame, Flow Control), reassembles multi-frame messages from their constituent Consecutive Frames, and enriches every matching frame with protocol metadata as CanKing frame properties.

It can also be configured to actively participate in transfers by sending Flow Control (FC) frames — both the initial CTS after a First Frame and subsequent CTS frames at block boundaries when fc_block_size > 0.

What It Does

Passive Observer Scope

Remove all active_addresses entries to turn the extension into a passive observer.

When active_addresses is configured, the extension sends FC(ContinueToSend) frames so the sender proceeds with data transfer.

Note:
This extension never sends segmented messages of its own. It can only receive segmented messages, not transmit.

Frame Properties Added

Depending on frame type and decode state, the extension sets these frame properties:

PropertySet onValue
ISOTP.FrameTypeAll recognised frames"SF", "FF", "CF", or "FC"
ISOTP.TpTotalBytesSF; FFPayload/Total message length in bytes
ISOTP.TpFirstDataHexFFHex of data bytes carried in the FF itself
ISOTP.TpSeqNoCFSequence number nibble (0–15)
ISOTP.TpSessionProgressCF"received/total" byte count
ISOTP.TpFlowStatusFC"CTS", "Wait", "Overflow", or "Reserved"
ISOTP.TpBlockSizeFCBlock size byte value
ISOTP.TpSeparationTimeUsFCSTmin decoded to microseconds
ISOTP.TpReassemblyCompleteLast CF of a complete message"true"
ISOTP.TpPayloadHexSF; last CF of a complete messageUppercase hex string of payload / reassembled data
ISOTP.TpActiveActionFF (on active FC send); CF at block boundary"FC sent"

Configuration

Configuration is JSON and can be changed at runtime via the CanKing extension config panel.

Default configuration:

{
  "session_timeout_ms": 1000,
  "extended_addressing": false,
  "extended_id": false,
  "active_addresses": [
    {
      "rx_can_id": 2024,
      "tx_can_id": 2016,
      "rx_address_extension": null,
      "tx_address_extension": null
    }
  ],
  "broadcast_id": 2015,
  "fc_block_size": 0,
  "fc_stmin": 0,
  "fc_padding": 204,
  "fc_use_brs": false
}

The default active_addresses, fc_padding, and broadcast_id values correspond to the standard OBD-II engine ECU scenario:

HexDecimalRole
0x7E82024Engine ECU response address (rx_can_id)
0x7E02016Tester physical request address (tx_can_id)
0x7DF2015OBD-II functional broadcast address (broadcast_id)
0xCC204ISO 15765-2 recommended padding byte (fc_padding)

Fields:

Active Receiver Flow

When fc_block_size = 0 (unlimited):

ECU → FF (on rx_can_id)    → extension sends FC(BS=0) on tx_can_id
ECU → CF sn=1
ECU → CF sn=2
…
ECU → CF last              → message reassembled, ISOTP.TpPayloadHex annotated

When fc_block_size = 2:

ECU → FF (on rx_can_id)    → extension sends FC(BS=2)
ECU → CF sn=1
ECU → CF sn=2              → extension sends FC(BS=2)   ← block boundary
ECU → CF sn=3
ECU → CF sn=4              → extension sends FC(BS=2)   ← block boundary
…
ECU → CF last              → message reassembled