ASTM

Read an analyzer's ASTM traffic, and never get a confident wrong value.

@cosyte/astm reads the delimiters each header declares, decodes escapes before it splits a value, verifies frame checksums, and reports every deviation it tolerated as a stable, value-free warning. Zero runtime dependencies.

@cosyte/astm
npm install @cosyte/astm

Need it integrated? Talk to us.

The standard

ASTM E1381 and E1394 carry results from lab instruments to computers.

  • ASTM E1381 specifies the low-level protocol for exchanging data between clinical instruments and computer systems, over serial links and TCP/IP, and points to E1394 for the message content. ASTM lists it as withdrawn in 2002. Source: ASTM, E1381-02
  • CLSI LIS01-A2 describes the electronic transmission of digital information between clinical laboratory instruments and computer systems. Source: CLSI, LIS01
  • CLSI LIS02 defines the two-way transmission of test requests, results and demographic information between laboratory instruments and information systems, and its revisions set it apart from the former ASTM version. Source: CLSI, LIS02

@cosyte/astm

Both layers, framing and records, read without assumptions.

Every analyzer reads the standard a little differently, and the usual answer is a hand-rolled split on | and ^ that returns a confidently wrong value the first time a vendor escapes a delimiter. This library surfaces a deviation it cannot resolve instead of resolving it for you.

  • Records per E1394 and LIS02-A2: H, P, O, R, C, Q, M, S and L. An unrecognized record type is surfaced, never dropped.
  • Framing per E1381 and LIS01-A2: modulo-256 checksums, frame-number sequencing, the 240-byte multi-frame split, and a socket-free ENQ, ACK, NAK and EOT receiver state machine.
  • Delimiters come from each header, never from an assumption, and escapes are decoded before a value is split.
  • Practice-assigned and laboratory-assigned patient IDs stay distinct.
  • Result status and abnormal flags are read fail-safe: a corrected or cancelled result never reads as final.
  • Emit with computed checksums and frame numbers; both layers round-trip by construction.
  • Map an analyzer's local test codes to LOINC through an LIVD catalog you supply.
read-results.tsts
import { parseAstmRecords, patient, results } from "@cosyte/astm";

// Synthetic ASTM records, CR-delimited. The header declares the delimiters.
const stream =
  "H|\\^&|||analyzer^1|||||||P|LIS02-A2|20240115103000\r" +
  "P|1|PRACTICE-0001|LAB-0002|||||F\r" +
  "O|1|SPEC-7|ACC-42|^^^687|||20240115102500\r" +
  "R|1|^^^687|28.6|U/L|10-40|N||F\r" +
  "L|1|N\r";

const msg = parseAstmRecords(stream);
const [first] = results(msg);

console.log(first?.value, first?.units);
console.log(first?.status.meaning, first?.status.isActiveFinal);
console.log(first?.flag?.meaning);
console.log(first?.universalTestId?.localCode);
console.log(patient(msg)?.practiceAssignedId, patient(msg)?.laboratoryAssignedId);
console.log(msg.warnings.length);

From the @cosyte/astm README on GitHub, verbatim. Every value in it is synthetic.

Limits

What it does not do.

Its README names what is still moving and what is not covered:

  • No named per-vendor profile ships yet, only a default and a reference profile grounded in a public corpus.
  • Three behaviors are the library's reading of the standard rather than a quotation: the paywalled LIS02 sections were not read.
  • No citable published source binds the result-status letter set, and every interpreted status says so.
  • The wire is read as Latin-1, one byte per character.
  • No LOINC, SNOMED or LIVD dictionary is bundled, and no LOINC is ever guessed.

The full status and limits, in the README

Alternatives

What else you could use.

Each description comes from the project’s own documentation or listing, linked below.

Python library

python-astm

A BSD-licensed Python implementation of the ASTM E1381 and E1394 protocol, published on PyPI as astm. Its last release on PyPI dates from March 2013.

Source: PyPI, astm

Node.js library

node-astm

An MIT-licensed Node.js package described as reading data from ASTM. Its latest npm release dates from February 2021.

Source: npm, node-astm

Platform agent

Medplum Agent

An application that runs inside your firewall and connects to devices over low-level protocols such as HL7/MLLP, ASTM and DICOM, as part of the Medplum platform.

Source: Medplum documentation, Agent

Works with

  • HL7 v2Results often continue downstream as HL7 v2 ORU messages: @cosyte/hl7.
  • Terminology@cosyte/terminology works over the LOINC release you supply.
  • @cosyte/synthGenerates synthetic ASTM records and framed transfers, including vendor-quirk fixtures.
  • @cosyte/datesConverts and validates the dates the @cosyte parsers return, without inventing a midnight or a timezone.

Try @cosyte/astm on your own messages.

It is free and MIT-licensed. If it saves you a day, a star on GitHub helps other engineers find it.

Need it integrated? Talk to us, or see what our integration services cover.