std.edi.messages

Infrastruktur-Nachrichten für den EDIFACT-Austausch: Empfangsquittungen, Fehlermeldungen und Freitext. Diese Nachrichten sind kein Geschäftsinhalt, sondern die technische Kommunikationsebene zwischen zwei EDI-Partnern.

  • CONTRL — Syntax-Quittung (positiv oder negativ). Jeder empfangene Interchange wird quittiert.
  • APERAK — Anwendungsebenen-Fehlermeldung. Wird nach erfolgreicher Syntax-Prüfung gesendet, wenn eine Nachricht inhaltlich abgelehnt wird.
  • GENRAL — Freitext-Nachricht für alles, was kein eigenes Message-Format hat.

import std.edi.messages;
import std.alloc;
import std.string;

fn Feld(p: int64, l: int64): pchar {
    var b: int64 := alloc(l + 1);
    var i: int64 := 0;
    while (i < l) { poke8(b + i, peek8(p + i)); i := i + 1; }
    poke8(b + l, 0);
    return b as pchar;
}

fn main(): int64 {
    var out: int64 := alloc(2048);

    // 1. Positive Syntaxquittung auf den Interchange IC000042
    var n: int64 := EdiContrlOk("IC000042"c, "4098765000004"c,
                                "4012345000009"c, out, 2048);
    PrintLn(Feld(out, n));

    var res: int64 := alloc(EDI_CONTRL_SIZE);
    EdiContrlRead(out, n, res);
    PrintLn(StrConcat("Status: ", IntToStr(peek64(res + EDI_CONTRL_STATUS))));

    // 2. Ablehnung: Pflichtsegment fehlt, Segmentposition 12
    n := EdiContrlErr("IC000042"c, 12, EDI_ERR_MISSING_SEG, out, 2048);
    PrintLn(Feld(out, n));
    EdiContrlRead(out, n, res);
    PrintLn(StrConcat(StrConcat("Status: ", IntToStr(peek64(res + EDI_CONTRL_STATUS))),
            StrConcat("  Fehlercode: ", IntToStr(peek64(res + EDI_CONTRL_ERRCODE)))));

    // 3. Fachliche Ablehnung (APERAK)
    n := EdiAperakWrite("BST-2026-0815"c, 14,
                        "Artikel 04012345678918 unbekannt"c, out, 2048);
    PrintLn(Feld(out, n));
    var ap: int64 := alloc(EDI_APERAK_SIZE);
    EdiAperakRead(out, n, ap);
    PrintLn(StrConcat("APERAK-Text: ", Feld(peek64(ap + EDI_APERAK_TEXT), peek64(ap + EDI_APERAK_TEXTLEN))));
    return 0;
}

UNB+UNOA:1+4098765000004+4012345000009+000000:0000+IC000042'UNH+1+CONTRL:1:901:UN'UCI+IC000042+4012345000009+4098765000004+7'UNT+3+1'UNZ+1+IC000042'
Status: 7
UNB+UNOA:1+++000000:0000+IC000042'UNH+1+CONTRL:1:901:UN'UCI+IC000042+++4+25+12'UNT+3+1'UNZ+1+IC000042'
Status: 4  Fehlercode: 25
BGM+313++9'RFF+ACE:BST-2026-0815'ERC+14'FTX+AAO++Artikel 04012345678918 unbekannt'
APERAK-Text: Artikel 04012345678918 unbekannt

 
CONTRL bringt seinen Umschlag selbst mit. EdiContrlOk und EdiContrlErr schreiben einen vollständigen Interchange von UNB bis UNZ — anders als die Fachnachrichten (ORDERS, INVOIC …), die nur den Rumpf liefern und den Umschlag aus std.edi.core brauchen. Das Datum bleibt dabei auf 000000:0000; wer ein echtes Datum braucht, baut die Quittung von Hand mit EdiUnbWrite.

EdiContrlErr trägt keine Partner-IDs ein (die Felder bleiben leer) — für den Versand an einen konkreten Partner den Umschlag selbst erzeugen.

Imports

  • std.edi.core
  • std.alloc

Structs

EdiContrl (EDI_CONTRL_SIZE = 40 Bytes)

Offset-Konstante Inhalt
EDI_CONTRL_STATUS Status: 7=akzeptiert, 4=abgelehnt (Gruppen-Ebene), 5=abgelehnt (Nachrichten-Ebene)
EDI_CONTRL_ERRCODE UN/EDIFACT-Fehlercode (0 = kein Fehler)
EDI_CONTRL_SEGPOS Position des fehlerhaften Segments (0 = Interchange-Ebene)
EDI_CONTRL_ICREF / EDI_CONTRL_ICREFLEN Zeiger auf die ICR des quittierten Interchange

Status-Konstanten:

Konstante Wert Bedeutung
EDI_CONTRL_ACCEPTED 7 Interchange vollständig akzeptiert
EDI_CONTRL_REJECTED4 4 Funktionale Gruppe abgelehnt
EDI_CONTRL_REJECTED5 5 Nachricht abgelehnt

Standard-Fehlercodes (UN/EDIFACT S005):

Konstante Wert Bedeutung
EDI_ERR_SYNTAX_VER 2 Syntax-Version nicht unterstützt
EDI_ERR_TEST_FLAG 7 Testflag-Mismatch
EDI_ERR_INVALID_VALUE 14 Ungültiger Wert
EDI_ERR_MISSING_SEG 25 Pflicht-Segment fehlt

EdiAperak (EDI_APERAK_SIZE = 40 Bytes)

Offset-Konstante Inhalt
EDI_APERAK_ERRCODE Anwendungs-Fehlercode
EDI_APERAK_REFMSG / EDI_APERAK_REFLEN Zeiger auf referenzierte Nachrichten-ID
EDI_APERAK_TEXT / EDI_APERAK_TEXTLEN Zeiger auf Fehlertext

EdiGenral (EDI_GENRAL_SIZE = 48 Bytes)

Offset-Konstante Inhalt
EDI_GENRAL_SUBJECT / EDI_GENRAL_SUBJLEN Betreff (aus BGM/C002)
EDI_GENRAL_BODY / EDI_GENRAL_BODYLEN Textkörper — alloziert, Caller muss freigeben
EDI_GENRAL_REFMSG / EDI_GENRAL_REFLEN Referenz auf die zugrundeliegende Nachricht

Achtung GENRAL-Body: EdiGenralRead alloziert einen Puffer für den zusammengesetzten FTX-Inhalt. Nach der Verarbeitung freigeben mit:

free(peek64(result + EDI_GENRAL_BODY), peek64(result + EDI_GENRAL_BODYLEN));


Funktionen

CONTRL — Syntax-Quittung

Signatur Beschreibung
EdiContrlOk(icRef: int64, senderId: int64, receiverId: int64, out: int64, outMax: int64): int64 Schreibt positive CONTRL-Quittung (UCI-Status 7)
EdiContrlErr(icRef: int64, segPos: int64, errCode: int64, out: int64, outMax: int64): int64 Schreibt negative CONTRL-Quittung mit Fehlerposition und -Code
EdiContrlRead(buf: int64, bufLen: int64, result: int64): int64 Parst CONTRL; befüllt result (EDI_CONTRL_SIZE). Gibt EDI_OK oder Fehlercode.

APERAK — Anwendungs-Fehlermeldung

Signatur Beschreibung
EdiAperakWrite(refMsgId: int64, errCode: int64, errText: int64, out: int64, outMax: int64): int64 Schreibt APERAK-Nachricht; errText ist null-terminiert (oder 0 für kein Text)
EdiAperakRead(buf: int64, bufLen: int64, result: int64): int64 Parst APERAK; befüllt result (EDI_APERAK_SIZE)

GENRAL — Freitext-Nachricht

Signatur Beschreibung
EdiGenralWrite(subject: int64, body: int64, refMsgId: int64, out: int64, outMax: int64): int64 Schreibt GENRAL; body wird als FTX-Segmente eingebettet
EdiGenralRead(buf: int64, bufLen: int64, result: int64): int64 Parst GENRAL; alloziert Puffer für Body — nach Gebrauch freigeben

Auswertung einer eingehenden Quittung

import std.edi.messages;
import std.alloc;
import std.string;

fn main(): int64 {
    var out: int64 := alloc(2048);
    var n: int64 := EdiContrlErr("IC000042"c, 5, EDI_ERR_INVALID_VALUE, out, 2048);

    var res: int64 := alloc(EDI_CONTRL_SIZE);
    EdiContrlRead(out, n, res);

    if (peek64(res + EDI_CONTRL_STATUS) == EDI_CONTRL_ACCEPTED) {
        PrintLn("Interchange akzeptiert.");
    } else {
        PrintLn(StrConcat("Interchange abgelehnt, Fehlercode: ",
                IntToStr(peek64(res + EDI_CONTRL_ERRCODE))));
        PrintLn(StrConcat("Fehlerhaftes Segment: ",
                IntToStr(peek64(res + EDI_CONTRL_SEGPOS))));
    }
    free(res, EDI_CONTRL_SIZE);
    free(out, 2048);
    return 0;
}

Interchange abgelehnt, Fehlercode: 14
Fehlerhaftes Segment: 5


Hinweise

  • Reihenfolge im Betrieb: erst CONTRL (Syntax), dann — falls die Nachricht syntaktisch in Ordnung war, fachlich aber scheitert — APERAK. Eine fachliche Ablehnung ersetzt die Syntaxquittung nicht.
  • EdiAperakWrite kürzt den Fehlertext auf EDI_FTX_MAX (512 Zeichen).
  • GENRAL-Body ist alloziert: EdiGenralRead legt für den zusammengesetzten FTX-Text einen eigenen Puffer an. Nach Gebrauch mit free(peek64(result + EDI_GENRAL_BODY), peek64(result + EDI_GENRAL_BODYLEN)) freigeben — das ist die einzige Stelle in std.edi, an der die Bibliothek selbst alloziert.
  • Alle Text-Parameter sind Zeiger auf nullterminierten Text ("IC000042"c as int64); nur segPos und errCode sind echte Zahlen.

Quelldatei

Unit Datei
std.edi.messages std/edi/messages.lyx

Letzte Aktualisierung: 2026-08-13 — Beispiele lauffähig gemacht und ausgeführt (lyxc 1.0.17K); festgehalten, dass CONTRL einen vollständigen Interchange erzeugt (Fachnachrichten dagegen nur den Rumpf) und dass EdiContrlErr keine Partner-IDs setzt

Codebeispiele geprüft: gegen lyxc 1.2.5C übersetzt (Prüflauf 2026-09-08 über die gesamte Doku: 574 Vollprogramme, 0 echte Fehler; zusätzlich 5159 Aufrufe gegen die pub fn-Signaturen in aurum/std gehalten, 0 Abweichungen).