====== std.hl7 — HL7 v2 Messaging ======
Vier Units für HL7 Version 2 — der im Gesundheitswesen meistverbreitete Nachrichtenstandard. ''std.hl7'' deckt den gesamten Stack ab: MLLP-TCP-Framing, MSH/ACK-Engine, Patientenverwaltung (ADT), Auftragswesen (ORM/OML) und Befundübermittlung (ORU/OUL).
→ [[lyx_-_programmiersprache:start|Übersicht]] · [[lyx_-_programmiersprache:units|Standard Library]] · [[lyx_-_programmiersprache:guides:welche-unit|Welche Unit?]]
----
===== Units =====
^ Unit ^ WP ^ Beschreibung ^
| [[lyx_-_programmiersprache:units:hl7:core|std.hl7.core]] | WP-HL7-00 | MLLP-Framing (VT+FS+CR), MSH-Parser, ACK-Generator, Duplikatserkennung (FNV1a-Ring), Versions- und Testmodus-Prüfung |
| [[lyx_-_programmiersprache:units:hl7:adt|std.hl7.adt]] | WP-HL7-01 | Patient Administration: ADT^Axx parsen/schreiben; PID, PV1, MRG, NK1; automatische Merge-Erkennung (A34–A45) |
| [[lyx_-_programmiersprache:units:hl7:orders|std.hl7.orders]] | WP-HL7-02 | Order Management: ORM^O01, OML^O21, RAS^O17 parsen/schreiben; ORC, OBR, RXA; STAT-Erkennung; ORR^O02/ORL^O22-Quittung |
| [[lyx_-_programmiersprache:units:hl7:results|std.hl7.results]] | WP-HL7-03 | Result Reporting: ORU^R01, OUL^R22 parsen/schreiben; OBX (Panikwert- und Korrektur-Flags), NTE-Kommentare |
Alle Units importieren ''std.hl7.core''.
----
===== Was ist HL7 v2? =====
HL7 (Health Level 7) Version 2 ist der faktische Standard für Datenintegration in Krankenhäusern. Jede Nachricht besteht aus zeilentrennend (CR) geschriebenen **Segmenten** (3 Großbuchstaben + ''|''), die wiederum ''|''-getrennte Felder und ''^''-getrennte Komponenten enthalten:
MSH|^~\&|LIS|HOSPITAL|HIS||20260616083000||ORU^R01|MSG001|P|2.5.1
PID|||PAT123^^^MPI||Muster^Max||19850315|M
OBR|1|ORD042|LAB042|1743-4^Glucose^LN|||20260616082000
OBX|1|NM|1743-4^Glucose^LN||195|mg/dL|70-99||||HH||F
Die Standard-Trennzeichen sind: Feld: ''|'', Komponente: ''^'', Wiederholung: ''~'', Escape: ''\\'', Subkomponente: ''&''.
----
===== MLLP-Framing =====
HL7 v2-Nachrichten werden über TCP immer im **MLLP-Frame** übertragen (Minimal Lower Layer Protocol):
[VT=0x0B] + HL7-Nachrichtenbytes + [FS=0x1C] + [CR=0x0D]
''MllpFrameWrite'' legt den Rahmen um eine fertige HL7-Nachricht; ''MllpFrameRead'' extrahiert die Nachricht aus dem TCP-Empfangspuffer.
----
===== Designprinzipien =====
* **Zero-Copy-Parsing**: Alle Parse-Funktionen speichern Zeiger in den Originalnachrichtenpuffer — keine String-Kopien. Der Puffer muss während der Struct-Verwendung gültig bleiben.
* **Caller alloziert**: Alle Structs (MSH, PID, PV1, ADT, Order, Report, OBX) werden vom Caller alloziert. Größenkonstanten (''HL7_*_SIZE'') geben die benötigte Byte-Anzahl.
* **Kein rekursiver Besitz**: Eine geparste ORU-Nachricht enthält einen Befundkopf (''Hl7OruParse'') — die einzelnen OBX-Segmente müssen getrennt über ''Hl7ObxParse'' in Schleife geparst werden.
* **Implizite Typprüfung**: ''HL7_ORD_ISSTAT'' und ''HL7_OBX_ISCRIT''/''HL7_OBX_ISCORR'' werden automatisch gesetzt — keine manuellen String-Vergleiche nötig.
----
===== Nachrichtenflüsse =====
==== Patientenaufnahme (ADT) ====
HIS/ADT-System HL7-Gateway / Lyx
| |
|-- ADT^A01 (Aufnahme) -->| Hl7AdtParse()
|<-- ACK^AA (Quittung) --| Hl7AckWrite() + MllpFrameWrite()
| |
|-- ADT^A08 (Update) --->| Hl7AdtParse()
|<-- ACK^AA -------------|
| |
|-- ADT^A03 (Entlassung)->| Hl7AdtParse()
|<-- ACK^AA -------------|
==== Laborauftrag und Befund (ORM → ORU) ====
KIS / Station LIS (Labor)
| |
|-- ORM^O01 (Auftrag) -->| Hl7OrmParse()
|<-- ORR^O02 (OK/ER) ----| Hl7OrrWrite()
| | [Analyse läuft ...]
|<-- ORU^R01 (Befund) ---| Hl7OruWrite() + Hl7ObxParse()
|-- ACK^AA -------------->|
==== Medikamentengabe (RAS) ====
Medikamentensystem Stationssystem
| |
|-- RAS^O17 ------------>| Hl7RasParse()
|<-- ACK^AA -------------|
----
===== Struct-Größentabelle =====
^ Struct ^ Konstante ^ Bytes ^ Zweck ^
| Hl7Msh | ''HL7_MSH_SIZE'' | 192 | MSH-Header einer beliebigen Nachricht |
| Hl7State | ''HL7_STATE_SIZE'' | 8448 | Dedup-State (16 Partner × 528 Bytes) |
| Hl7Pid | ''HL7_PID_SIZE'' | 176 | Patient Identification |
| Hl7Pv1 | ''HL7_PV1_SIZE'' | 160 | Patient Visit / Stationsbelegung |
| Hl7Mrg | ''HL7_MRG_SIZE'' | 48 | Patient Merge |
| Hl7Nk1 | ''HL7_NK1_SIZE'' | 48 | Next of Kin / Angehörige |
| Hl7Adt | ''HL7_ADT_SIZE'' | 544 | Vollständige ADT-Nachricht (PID+PV1+MRG+NK1) |
| Hl7Order | ''HL7_ORD_SIZE'' | 192 | Auftragsstruktur (ORC+OBR+PID+PV1) |
| Hl7RxAdmin | ''HL7_RXA_SIZE'' | 112 | Medikamentengabe (RXA) |
| Hl7ObxResult | ''HL7_OBX_SIZE'' | 144 | Einzelbeobachtung mit Panikwert-Flag |
| Hl7NteNote | ''HL7_NTE_SIZE'' | 16 | Kommentar (NTE) |
| Hl7Report | ''HL7_RPT_SIZE'' | 104 | Befundkopf (OBR+PID ohne OBX) |
----
===== Quickstart =====
import std.hl7.core;
import std.hl7.adt;
import std.alloc;
fn main(): int64 {
// Dedup-State initialisieren (einmalig pro Server-Instanz)
var state: int64 := alloc(HL7_STATE_SIZE);
Hl7StateInit(state);
// Aus TCP-Empfangspuffer: MLLP-Frame lesen
var tcpBuf: int64 := alloc(65536);
var msgBuf: int64 := alloc(65536);
// ... tcpBuf aus Socket befüllen ...
var msgLen: int64 := MllpFrameRead(tcpBuf, tcpBufLen, msgBuf, 65536);
if (msgLen < 0) { return 1; }
// MSH parsen
var msh: int64 := alloc(HL7_MSH_SIZE);
if (Hl7MshParse(msgBuf, msgLen, msh) != HL7_OK) {
free(msh, HL7_MSH_SIZE);
return 1;
}
// ADT-Nachricht vollständig parsen
var adt: int64 := alloc(HL7_ADT_SIZE);
Hl7AdtParse(msgBuf, msgLen, adt);
var pid1: int64 := peek64(adt + HL7_ADT_PID + HL7_PID_ID1);
var bed: int64 := peek64(adt + HL7_ADT_PV1 + HL7_PV1_LBED);
// ACK zurücksenden
var ackBuf: int64 := alloc(512);
var ackLen: int64 := Hl7AckWrite(msh, "AA"c as int64, "OK"c as int64, ackBuf, 512);
var outBuf: int64 := alloc(600);
MllpFrameWrite(outBuf, 600, ackBuf, ackLen);
free(outBuf, 600);
free(ackBuf, 512);
free(adt, HL7_ADT_SIZE);
free(msh, HL7_MSH_SIZE);
free(msgBuf, 65536);
free(tcpBuf, 65536);
free(state, HL7_STATE_SIZE);
return 0;
}
----
Letzte Aktualisierung: 2026-06-16