JS decoder for scanner payloads from the German Bundeseinheitlicher Medikationsplan (BMP).
The package does not scan camera input or images. BMP printouts use a DataMatrix 2D barcode whose payload is compact ISO-8859-1 XML; this package starts after a scanner has already returned that payload text or bytes.
This package is part of the AvatarMediKI project. More project context is available at anabox-smart.de/ki.
Install bmp-reader from npm with npm install:
npm install bmp-readerRequires Node.js 20 or newer.
import { decodeBmp, decodeBmpPages } from "bmp-reader";
const plan = decodeBmp(scannerText);
console.log(plan.patient.firstName);
console.log(plan.medications);
const combined = decodeBmpPages([page1ScannerText, page2ScannerText]);
console.log(combined.sections);decodeBmp() accepts a string, Uint8Array, or ArrayBuffer. Byte inputs are decoded with exact Latin-1 byte mapping.
The static demo in docs/ can be served directly by GitHub Pages:
- GitHub Pages URL after enabling Pages: utzel-butzel.github.io/bmp-reader
- Local preview:
npm run demo:dev - Rebuild the browser decoder bundle:
npm run build:demo
The demo accepts pasted BMP payload XML, reads DataMatrix barcodes from webcam or image files with zxing-wasm, includes anonymized sample payloads, assembles multi-page examples, and shows the decoded plan as overview cards, medication rows, section items, warnings, JSON, and formatted XML.
Use a scanner or barcode library that can read DataMatrix codes and preserve the BMP payload as ISO-8859-1/Latin-1 data. BMP payloads are compact XML, but they are not UTF-8; German characters such as ä, ö, ü, ß, or Ü must survive as Latin-1 bytes.
Recommended scanner handoff:
- Prefer passing raw scanner bytes to
decodeBmp()asUint8ArrayorArrayBuffer. - If your scanner returns text, make sure it maps each byte directly to the same JavaScript character code (
0x00to0xff) instead of transcoding from UTF-8. - For multi-page BMP printouts, scan each DataMatrix separately and pass the page payloads to
decodeBmpPages(). - Keep camera, image, PDF, or hardware scanning code in your application; this package intentionally only decodes the returned BMP XML payload.
Recommended scanner/decoder tools:
- Hardware scanners: use a 2D imager that explicitly supports DataMatrix ECC200. Configure it as USB HID keyboard wedge, USB serial, or native serial depending on your app, and verify that it does not transcode Latin-1 payload bytes as UTF-8.
- Browser or Node image decoding:
zxing-wasmis a good JS option because it supports DataMatrix and can read from browser image data or Node buffers. - CLI or CI checks:
dmtxreadfromlibdmtxis useful for DataMatrix-only fixture validation. - Native browser scanning: the
BarcodeDetectorAPI can be useful where available, but feature-detectBarcodeDetector.getSupportedFormats()and only use it for BMP whendata_matrixis supported in your target browsers.
Version support refers to the XML MP.v attribute in the scanner payload.
| BMP version | Default status | Notes |
|---|---|---|
028 / v2.8 |
Supported | Included in the default supportedVersions; covered by official/public fixtures. |
027 / v2.7 |
Supported | Included in the default supportedVersions; covered by specification examples. |
026 / v2.6 |
Opt-in compatibility | Not supported by default. Historical XML fixtures parse with allowUnknownVersion: true, but this is not claimed as full support. |
023 / v2.3 |
Opt-in compatibility | Not supported by default. Historical XML fixtures parse with allowUnknownVersion: true, but this is not claimed as full support. |
| Other XML versions | Not supported by default | decodeBmp() throws UNSUPPORTED_VERSION unless allowUnknownVersion or a custom supportedVersions list is provided. |
Pipe-delimited MP|020|... |
Not supported | This older non-XML carrier format is intentionally rejected. |
Decodes one BMP carrier XML payload.
Options:
allowUnknownVersion: return data with a warning instead of throwing for unknown BMP versions.supportedVersions: defaults to["027", "028"].
Decodes and assembles all pages of a multi-page BMP. It validates that pages share the same instance ID and version, detects missing or duplicate pages, sorts pages, and merges adjacent sections with the same heading.
Thrown errors expose a stable code and a details object.
Known error codes include:
MALFORMED_XMLWRONG_ROOTUNSUPPORTED_VERSIONMISSING_REQUIRED_ROOT_FIELDMISSING_REQUIRED_FIELDMISSING_PAGEDUPLICATE_PAGEINVALID_PAGE_ASSEMBLYINVALID_INPUT
The decoder preserves raw attributes and unknown attributes. It does not resolve PZN values or access an Arzneimitteldatenbank; PZN-only medication entries are returned with warnings because display data may need an external drug database.
Real-world BMP payloads help catch edge cases that official examples and synthetic fixtures miss. If you can share an anonymized Medikationsplan payload, please open an issue or pull request with the scanner text/bytes or compact XML plus the BMP version if you know it.
Please only share data that is fully anonymized. Do not send real patient data, names, birth dates, insurance numbers, addresses, doctor or practice names, IDs, or identifying free-text notes. When in doubt, replace values with synthetic data while keeping the same XML structure.
The library is authored in TypeScript and compiled to dist/.
npm run typecheck
npm run build
npm testThe test suite includes official/public fixtures from the v2.8 BMP_Beispieldateien_V2.8.zip sample and the v2.7 barcode-content example printed in the BMP specification. It also keeps historical v2.6 and v2.3 specification examples as permissive-version fixtures, plus synthetic fixtures for multi-page and edge-case behavior. Barcode, generated-PDF, downloaded public-PDF, and downloaded public-image scanning tests are test-only and are not exported by the package; one public image fixture covers the older pipe-delimited MP|020|... carrier format as an intentionally rejected non-XML payload.
