Z-bit

The .osdpcap file format

An .osdpcap file records the OSDP packets on a link, one per line, with when each was seen and which way it went. It's what the Capture Analyzer reads.

Overview

An .osdpcap file is JSON Lines: UTF-8 text with one JSON object per line. Each object is a record of one OSDP packet, a command or a reply, exactly as it crossed the wire. Records are written in the order the packets were seen. The format is defined by the OSDP Capture Format specification in libosdp-conformance; this page describes version 1.

These tools write it:

  • The OSDP.Net ACU and PD Consoles, in the captures folder beside the app.
  • The OSDP.Net library, when a connection is started with tracing on ({connection id}.osdpcap in the working directory), or from your own code with OSDPCaptureFileWriter.
  • OSDP Bench, when you export a packet trace as an OSDP Capture.
  • libosdp-conformance.

Record fields

Every record has all six fields, and every value is written as a JSON string, numbers included.

FieldValue
timeSecWhole seconds since the Unix epoch, UTC, in decimal. For example "1792944000".
timeNanoNanoseconds within that second, "000000000" to "999999999", zero-padded to nine digits. OSDP.Net tools record to 100 ns.
ioWhich way the packet went, seen from the tool that wrote the file: "output" it sent the packet, "input" it received the packet, "trace" it watched the line without taking part. So in an ACU Console capture commands are output and replies are input; in a PD Console capture it's the other way round.
dataThe bytes off the wire as hex, normally one whole packet from the start-of-message byte 53 through the checksum or CRC. OSDP.Net tools separate the bytes with dashes ("53-00-08-00-05-60-DA-99"); libosdp-conformance uses spaces. Leading FF mark bytes may be included. Secure Channel packets are recorded as sent, still encrypted.
osdpTraceVersionThe format version. This page describes version "1".
osdpSourceThe tool that wrote the record, such as "ACUConsole", "PDConsole", "OSDP.Net", "OSDP-Bench" or "libosdp-conformance 0.91-5".

Example

An ACU polling the reader at address 0 and the reader's acknowledgement 21 ms later:

{"timeSec":"1792944000","timeNano":"125000000","io":"output","data":"53-00-08-00-05-60-DA-99","osdpTraceVersion":"1","osdpSource":"ACUConsole"}
{"timeSec":"1792944000","timeNano":"146000000","io":"input","data":"53-80-08-00-05-40-68-9F","osdpTraceVersion":"1","osdpSource":"ACUConsole"}

The first packet is osdp_POLL (60) to address 00; the second is osdp_ACK (40) from the same device, with the reply bit set in its address byte (80). Both have sequence number 1 and a CRC-16.

JSON Schema

One line of an .osdpcap file, as JSON Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "osdpcap record",
  "type": "object",
  "required": ["timeSec", "timeNano", "io", "data", "osdpTraceVersion", "osdpSource"],
  "properties": {
    "timeSec": { "type": "string", "pattern": "^[0-9]+$" },
    "timeNano": { "type": "string", "pattern": "^[0-9]{1,9}$" },
    "io": { "enum": ["output", "input", "trace"] },
    "data": { "type": "string", "pattern": "^[\\s\\-:]*([0-9A-Fa-f]{2}[\\s\\-:]*)+$" },
    "osdpTraceVersion": { "const": "1" },
    "osdpSource": { "type": "string" }
  }
}

What the Capture Analyzer accepts

The analyzer reads captures more leniently than the specification requires, so files from tools that bend the format still work:

  • Files up to 25 MB. Blank lines are skipped.
  • The first line must be a JSON object. A decoded .txt trace is not an .osdpcap file.
  • Lines that can't be read are counted and reported in the analysis rather than failing the upload.
  • A record needs only timeSec and data; a missing timeNano is taken as 0. timeSec and timeNano may also be JSON numbers.
  • Commands and replies are told apart by the reply bit in each packet's address byte, so io isn't needed to decode a capture.
  • Each data value must hold one packet with an even number of hex digits; any separator is ignored.

Writing captures from your own code

With OSDP.Net, OSDPCaptureFileWriter writes records in this format:

using OSDP.Net.Tracing;

using var capture = new OSDPCaptureFileWriter("reader.osdpcap", "MyTool");
capture.WritePacket(commandBytes, TraceDirection.Output);
capture.WritePacket(replyBytes, TraceDirection.Input);

Pass capture.WriteTrace as the tracer when starting a ControlPanel connection to record every packet on the bus.