ASTM E1394 Frame Structure: A Technical Reference for Lab Integrators

L
LIS Bridge
Aug 12, 2026
ASTM E1394 Frame Structure: A Technical Reference for Lab Integrators

An ASTM E1394 tutorial covering record types, delimiters, and the E1381 frame layer — checksums, frame numbers, and the handshake that trips up integrators.

ASTM E1394 Frame Structure: A Technical Reference for Lab Integrators

Most people arrive at ASTM E1394 by way of a problem. An analyzer is emitting something over a serial port, it looks vaguely like pipe-delimited text, and it needs to end up in an LIS. The obvious move is to split on pipes and start mapping fields. That works for about a day, until a result arrives split across two frames, or a checksum mismatch silently drops a record, or the analyzer stops transmitting entirely because nobody answered its ENQ.

The reason this happens is that "ASTM" in lab integration is actually two standards stacked on top of each other, and the one people read about is the one that matters less operationally. This ASTM E1394 tutorial covers both layers: the message content layer that defines records and fields, and the transport layer underneath it that defines framing, sequencing, checksums, and the handshake. The second one is where integrations actually fail.

If you want the conceptual overview first, start with what ASTM E1394 is. This post assumes that context and goes to the byte level.

Two Standards, Two Jobs

ASTM E1381 is the low-level transport specification. It defines how bytes move across the physical link: session establishment, frame delimiters, frame numbering, checksums, acknowledgement, retransmission, and termination. It does not know or care what the data means.

ASTM E1394 is the message content specification. It defines record types, the field hierarchy, delimiters, and what belongs in each position. It assumes the bytes arrive intact and in order — E1381's job.

In practice people say "ASTM" for both, and the conflation is the source of most integration surprises. You can implement E1394 parsing perfectly and still fail to receive a single result, because the analyzer is waiting on an E1381 acknowledgement that never comes.

The E1381 Transport Layer

Session establishment

The link is idle until one side has something to send. The sender transmits ENQ (0x05) to request the line. The receiver replies ACK (0x06) to grant it, or NAK (0x15) to refuse — typically because it is busy. On refusal the sender waits and retries.

Contention happens when both sides send ENQ simultaneously. The standard resolves it by role: the analyzer typically yields to the computer system, waits a defined interval, and retries. Vendors vary in how strictly they implement this, and a contention bug usually presents as an interface that works fine until the day someone enables bidirectional ordering.

Frame structure

Once the line is granted, data moves in frames. A frame looks like this:

<STX> FN text <ETB|ETX> C1 C2 <CR> <LF>

Reading left to right:

  • STX (0x02) — start of the frame.
  • FN — a single ASCII digit, the frame number, cycling 0 through 7 and wrapping. This is how the receiver detects a lost or duplicated frame.
  • text — the E1394 record content, or a fragment of one.
  • ETB (0x17) or ETX (0x03) — ETX means this frame completes the record; ETB means the record continues in the next frame. Getting this distinction wrong is the classic cause of truncated results.
  • C1 C2 — the checksum, two uppercase hexadecimal characters.
  • CR LF (0x0D 0x0A) — frame terminator.

Frames are capped at 240 characters including overhead. A long record — a CBC with a full differential, or a result carrying an extended comment — will exceed that and be split. Any parser that assumes one record per frame will lose data on exactly the highest-value messages.

The checksum

The checksum is a modulo-256 sum of the character values from the frame number through the ETB or ETX inclusive, expressed as two uppercase hex digits. The STX itself is excluded; the terminating ETB/ETX is included.

Two implementation notes cause most of the bugs here. First, lowercase hex is a common vendor deviation — a strict comparison against uppercase will reject valid frames. Second, some implementations disagree about whether the frame number participates. If checksums fail universally against a specific analyzer, compute both variants and see which one the instrument agrees with; that is faster than reading the vendor manual.

Acknowledgement and retransmission

After each frame the receiver replies:

  • ACK — frame received, checksum valid, send the next one.
  • NAK — checksum failed or the frame was malformed. The sender retransmits the same frame with the same frame number.
  • EOT (0x04) — the receiver is aborting the transfer.

Retransmission is bounded. Convention is six attempts on a frame before the sender gives up and sends EOT, ending the session. Timers are specified but vendor-variable — a receiver typically allows a generous window for the next frame, a transmitter a shorter one for the acknowledgement. Treat published timer values as defaults to be verified per instrument rather than as guarantees.

When the message is complete, the sender transmits EOT and the line returns to idle.

This entire layer is invisible in the data. It never appears in a captured message body, which is precisely why it gets skipped by tooling built on the assumption that a message already exists.

The E1394 Content Layer

Delimiters

E1394 uses four delimiters, declared by the analyzer in the header record rather than fixed by the standard:

  • Record delimiter — CR, ends a record.
  • Field delimiter — conventionally |.
  • Repeat delimiter — conventionally \, separates repetitions within a field.
  • Component delimiter — conventionally ^, separates components within a field.
  • Escape character — conventionally &.

A header typically opens H|\^&, which is the analyzer declaring its delimiter set: field is |, then repeat, component, and escape in order. A robust parser reads the delimiters from the header rather than hard-coding them. Most analyzers use the conventional set; the ones that do not will break a hard-coded parser on the first message.

Record types

Each record begins with a single-character type identifier:

  • H — Header. Opens the message. Declares delimiters, sender ID, instrument identity, processing ID, version, timestamp.
  • P — Patient. Patient identifiers, name, date of birth, sex, and related demographics.
  • O — Order. The test order: specimen ID, universal test ID, priority, collection timestamp, action code, specimen descriptor.
  • R — Result. A single measured value: test ID, value, units, reference range, abnormal flags, result status, timestamps, operator.
  • C — Comment. Free text attached to the preceding record. Position matters — a comment following a result belongs to that result, not to the order.
  • Q — Request/Query. Used for host query: the analyzer asks the connected system what to run on a loaded sample.
  • S — Scientific. Rarely seen in routine clinical traffic.
  • M — Manufacturer. Vendor-defined extension. Where instrument-specific data that does not fit the standard ends up.
  • L — Terminator. Closes the message and carries a termination code.

Hierarchy and sequence numbers

Records nest. A message is one H, then one or more P records, each with one or more O records, each with one or more R records, with C records attachable at any level, closed by a single L.

The second field of each record is a sequence number that resets within its parent. Within one order, results number 1, 2, 3; the next order's results restart at 1. Parsers that treat the sequence number as globally unique will misassociate results across orders — a failure that produces plausible-looking output on a single-order message and scrambles a batch.

A minimal message, delimiters shown literally:

H|\^&|||AnalyzerName^1.0|||||||P|1|20260820103000
P|1||PID12345||DOE^JANE||19850312|F
O|1|SPEC0098||^^^CBC|R||20260820102400|||||||||||||||||F
R|1|^^^WBC|7.2|10*3/uL|4.0 to 11.0|N||F||TECH01|20260820102955
R|2|^^^RBC|4.61|10*6/uL|4.20 to 5.40|N||F||TECH01|20260820102955
L|1|N

Note the empty fields. Analyzers populate a small subset of the defined positions, and which subset differs by manufacturer and by firmware version on the same manufacturer. Positional assumptions are the single largest source of per-instrument parser work.

Host query

Bidirectional operation uses Q records. The analyzer scans a barcoded sample and transmits a query asking what tests to run. The connected system responds with an order message — H, P, O, L — carrying the pending worklist for that specimen.

The demanding part is not the record format. It is that the response must arrive inside the analyzer's query window, which is typically short. Miss it and the instrument falls back to manual programming, silently. That makes host query a latency requirement as much as a parsing one, and it is a common reason bidirectional integrations underperform in production despite passing a bench test.

An Integration Engine Is Not an Instrument Driver

This distinction deserves stating plainly, because a lot of lab integration budget is currently being spent on the wrong layer.

General healthcare integration engines — the Mirth-class tools and their commercial alternatives — are excellent at what they do. They route HL7 v2, FHIR, X12, and DICOM between systems, transform message formats, apply routing rules, and handle enterprise message volume reliably. If an HL7 message exists somewhere in your estate, these tools will move it anywhere you need it to go.

What they do not do is sit on an RS-232 port and run an E1381 session with a bench analyzer. They do not answer an ENQ, compute and verify frame checksums, manage cyclic frame numbers, reassemble a record split across ETB boundaries, negotiate contention, recover the link when a cable is knocked loose during a run, or build a Q-record worklist response inside an analyzer's query timeout.

That is the layer this article describes, and it is genuinely different work. It is stateful, timing-sensitive, per-vendor idiosyncratic, and it runs against physical hardware that fails in physical ways. Labs routinely buy an integration engine, correctly, for their HIS-to-EHR messaging — then discover that the last three feet, from the analyzer to something that produces an HL7 message in the first place, is still unsolved. The usual outcome is custom development per instrument, which is exactly the cost the engine was meant to avoid.

The useful question when evaluating any tool for lab connectivity is narrow: does it speak to the instrument, or does it move messages that something else already produced? Both are needed. They are not the same product.

Practical Parser Notes

Things worth building in from the start, each learned the expensive way:

  • Read delimiters from the header. Do not hard-code | and ^.
  • Buffer across ETB boundaries. Reassemble before parsing, always. Never parse a frame in isolation.
  • Compute both checksum variants during bring-up. Log which one the instrument agrees with, then lock it in per device.
  • Accept lowercase hex checksums. Compare case-insensitively.
  • Treat sequence numbers as parent-scoped. Never as globally unique.
  • Never assume field positions across vendors. Map per instrument, and re-verify after a firmware update.
  • Log the raw frames. When a result is questioned six months later, the parsed value is an assertion; the original frame is evidence. LISBridge stores raw protocol data alongside every parsed result for exactly this reason.
  • Design for the cable, not the happy path. Serial links get unplugged, switches reboot, machines lose power mid-run. Automatic reconnect with backoff and crash-safe local storage are not optional extras at this layer — they are the difference between an interface staff trust and one they route around.

Frequently Asked Questions

What is the difference between ASTM E1394 and ASTM E1381?

E1381 is the transport layer — framing, checksums, frame numbers, and the ENQ/ACK handshake that moves bytes across the link. E1394 is the content layer — record types, delimiters, and field structure. You need both. Implementing E1394 alone will parse a captured message correctly but will not establish a working session with an analyzer.

Why does my parser lose results on large panels?

Almost certainly frame reassembly. Records longer than the 240-character frame limit are split across frames terminated with ETB rather than ETX. If you parse each frame independently, long records — which is to say, the panels with the most results — get truncated. Buffer until you see ETX, then parse.

Is ASTM E1394 obsolete now that HL7 exists?

No, and the two are not competitors. They occupy different positions: E1394 is instrument-facing, from analyzer to middleware; HL7 is system-facing, from middleware to HIS or EHR. A large installed base of analyzers — including current models — speaks ASTM natively, and a typical data path runs analyzer → ASTM → middleware → HL7 → HIS.

Do all analyzers implement the standard the same way?

No, and planning otherwise is the main cause of schedule overrun on integration projects. Field usage, populated positions, delimiter choices, checksum details, timer behaviour, and manufacturer-record contents all vary by vendor and often by firmware version. This is why per-instrument parsers exist rather than a single generic ASTM parser. LISBridge ships parsers for 35 named analyzers precisely so this work is already done.

Can I test a parser without an analyzer?

Partly. You can validate E1394 record parsing against captured messages offline, and that catches content bugs. You cannot validate E1381 session behaviour — handshake, retransmission, contention, timeout handling — without either the instrument or a simulator that reproduces its timing. Session-layer bugs pass every offline test and appear in production.

Summary

ASTM in lab integration is two layers. The content layer is well documented, learnable in an afternoon, and where most tutorials stop. The transport layer is where sessions hang, results truncate, checksums mismatch, and links fail to recover — and it is the layer that generic integration tooling does not implement at all.

If you are building this yourself, budget your time accordingly: the record format is the easy half. If you would rather not, that is the layer LISBridge exists to handle. More on how parsing works on our data parsing page.

Start your free trial — no credit card required. lisbridge.com/pricing

Comments (0)

Leave a comment

No comments yet. Be the first to leave one!