How to write and send an ASTM frame to
medical equipment
Asked 4 years, 11. months agoModified 5 months agoViewed 11k times
| 21 currently working on the ASTM protocol to send orders tests request to medical
instrument. But | cannot send a message to the equipment correctly. To be more explicit, |
2. want for example to send these frames:
WH String 1, s2, s3, 54, 85, 56
AT = "Hie \yoov-tdfociwa-s6}fGenexpert PC*GeneXpert®4.8jiis|P|1394-97]20070S21100245";
d=
3 = “O|tISID-818l}4 MTestid-1245]20070812140509)IAlI]ORHIIi
sf = “O2I5ID-818||4* *Testid-14)5[20070812140609|I|Al]ORHIIl Is
85 = “O[3{S1D-818|/* Testid-1615|2007081214070o)IAlI|ORHII°s
86 = “LIF
and here is how | am doing now:
writeMeBytes(outToServer, h1.getBytes();
writeMeBytes(outToServer, s2.getBytes();
writeMeBytes(outToServer, s3.getBytes0);
writeMeBytes(outToServer, s4.getBytes();
writeMeBytes(outToServer, s5.getBytes0);
writeMeBytes(outToServer, s6.getBytes();
public static void writeMeBytes(DataQutputStream dos, byte [] b){
1 (b.length >0){
int} = 0;
while (<= blength-1) {
ty
doswrite(bl++);
} catch (IOException ex) {
Logger getLogger SimpleServer.class.getName())log(Level.SEVERE, null, ex)
| turn it into byte and then send byte after byte.
Except that I do not see any change on the receiver side.
Update according to @Muhammad Answer
This is what | did to send order to GeneXpert DX System
public class SimpleServer (private static ServerSocket server;
private static Socket connection;
public static void main(String args{)) throws IOException, InterruptedException {
server = new ServerSocket(12221);
boolean stopped = false:
System.out.printin( star."
connection = serveraccept0;
System.out.printin('wait for connection");
BufferedReader inFromClient = new BufferedReader(new
InputStreamReader(connection.getinputStream());
DataOutputStream outToClient = nev DataOutputStream(connection.getOutputStream0);
String currentsg =
int clientintMessage;
String ht, s2, 53, $4, s5,56 =";
hit = "1H]@\ODM-14fOGNWA-36]IGeneXpert PCAGeneXpert4.8ILis|P|1394-97/20070521 100245" +
ProtocolASCIL.LF
1" + ProtocolASCILLE
I1)S-816)}*4Testd-12)5[200708121 4050] ORI"
LINE" + ProtocolASCILLF;
s2 =I;
53 = "Oft[sID-B1a\|*¢Testid-12[s[20070812140500 All| OR]
sh = OR|S10-818|/** MTestld-14\5|20070812140600}I|A]ORHilll
1185 = °O)3|SID-816)|* *Testid-16|5]20070812140700}I4ll] ORM
36 = "UN
ProtocolASCILLF
String retmsg = h1;
‘{MaogException("OrderMessae + retmsg);
retmsg = ProtocolASCIISTX + retmsg + ProtocolASCII.CR + ProtocolASCILETX +
ProtocolMessage.getCheckSum(retmsg) + ProtocolASCILCR + ProtocolASCIL.LF;
clientintMessage = inFromClientread0,
HPohile (clientintMessage != ProtocolASCILEOT) ¢
while (true) {
currentMsg += String.valueOf(Character.toChars(clientintMessage));
# (clientintMessage == ProtocolASCILENQ) {
outToClientwriteBytes(" + ProtocolASCILACK);
System.out printin(* <--- US [ACK] on DX fENQN);
} elseif (clientintMessage == ProtocolASCILACK) {
‘System.out printin(* --> DX {ACKI");
11 Send your order message here
outToClientwriteBytes(retmsg);
) else if (clientintMessage == ProtocolASCII.CR) (
‘System .out printin(currentMsg);
outToClientwriteBytes(“ + ProtocolASCILACK);
) else if (clientint Message == ProtocolASCILNAK) {
System.out printin(* --> DX sent [NAKI");
‘System.out printing
Thread sleep(10000);
outToClientwriteBytes(“ + ProtocolASCILENQ);
US now wait 10 sec... );System out printin(* <-- US (ENA) *);
} else if (clientIntMessage == ProtocolASCII.EOT) {
System.out printin("--> DX END OF TRANSMISSION");
outToClient writeBytes(* + ProtocolASCIlENQ);
System out printin(” <-- US ENA)
# (stopped) {
break;
)
clientintMessage = infromClient read;
,
connection.closeO;
stopped = true
»
And this is the result | get from the console:
start.
wait for connection
<== LIS [ACK] on DX [ENQ]
1H|@*\]ODM-rQTGiIWA-6|GeneXpert PC*GeneXpert 4 sIllLs||P|1394-97]20180314003724
Q)ALL|I|O@N
urn
BS
> DX [EOT]
Us [ENQ)
> DX [ACK]
> DX sent [NAK]
~ LIS now wait 10 sec.
DX is the machine software and LIS is the host. Whenever I try to send the ENQ, the machine
answers me with NAK.
UPDATE 2
It seem to be working. But now windows events shows me an error about why my records
orders don't appear in the GeneXpert DX host record list. The header record have been sent
first.Sharelmprove this questionFollow edited Dec 16, 2020 at 15:57 asked Mar 12, 2018 at 15:00
kowsky Anatole ABE
116k 2 29 41 SiS 1 7 12Are you sure you should be using a DataOutputStream ? And using String get8ytes) without explicitly
specifying a character set is an accident waiting to happen. Also please clarify how it doesn't work. You're
not providing us a lot to go on. ~ Mark Rotteveel Mar 12, 2018 at 15:10 7
1 Luse DataOutputstream because the connexion is done by the socket, and i have to write bytes to
communicate with the receiver. As you can see in top, the string is firstly initialized before getfytes0 . To
be more explicit, | want to order the client to start a test by sending him the information on the patient
from the frame above. But the concern is that after typing orders that are lower, | do not see the result at
the client, Do you know how to translate ASTM request in JAVA? I take inspiration on this med
kim.com.tr/images/kataloglar/Sd7cc11c-e,pdf- Anatole ABE Mar 12, 2018 at 1637 7
A DataOutputStream is for writing a very specific data format, you likely need a plain. OutputStream
Mark Rotteveel Mar 12, 2018 at 17:39
Sorted by:
2 Answers
a!
8
Vv
a
v
®
Highest score (default)
Before answering, lets discuss machine mechanism for Bidirectional.
String ht, s2, 53, 54, 85, 56 =
1 = "HI@*\\}ODM-lafOGIWA-36||GeneXpert PC*GeneXpert4glis}PI1394-97120070521100245";
s2= "PIN"
83 = “O[t/SID-818]* *Testid-12[5|20070812140500}All|ORHl 2"
s4 = “O[sID-818]/* *Testid-14[s]20070812140609}IAll]ORMll
55 = “Of3SID-818]/* Testid-1615|20070812140700)IAlI|ORHIls
36 = "UNF
First, viewing above String message, there isn't any tag numbering as every machine | have
done so far requires Tag number. For example:
TH|\*8iI]]CS-2500%00-0822029" 8 *CPABV9B179IlIE1394-97
2P1II]o0000152556)JOHN*ABC||19440601|M|| ‘Dr Shaukat Khanum Hospitalllll|** EAST
30|1]000038%0140012586236"B||***0514 100,00¥4-* A044 “100.00)R|201803081225236||N
4utIN
So, you must have NUMBERING for each tag.
Second, Machine sends following query at first time:
THI\*BI]CS-2500% 8220298 ACPABV9B1798}l|E1394-9711
2Q|11000038%01% 00123658458]|** *040”PT-INN\* S050“ APTT-FS|o|201803081227007F
3utINF9
In, Query(2Q) Tag, 000038 rack id, 01 rack sequence number, 001H18074618 sample id (read
from Barcode), further information can be verified from host or LIS manual provided by
machine vendor.
Third, When we receive this message, we will make message for machine that | have described
above (writing again below) with additional checksum information. Again, this checksum can
be found in host or LIS manual of machine.THI\*BiI|]CS-2500%00-0822029%8CPABV981798|E1394-97
2P1|I]o0000152556)*JOHN*ABC||19440601|M|| ‘Dr Shaukat Khanum Hospitallll|*/* “EAST
30|1]000038401 1234567881 * 4051 “100.00%" 4 0444. 109,00|R|201803081225236l||N
4utIN
Example of Checksum calculation. Note that it may vary from machine to machine.
public static String getCheckSum(String msg) {
int sum = 0;
for (inti = 0;1 < msgulengthO: i++) (
sum += msg.charAt()
)
sum += 16; //adding CR and ETX AND ETB
sum = sum % 256;
String checksum = Integer.toHexString(sum).toUpperCase();
# (checksumJengthd == 1) (
checksum = "0" + checksum;
)
//System.out.printhn"\n Check Sum is ="+ checksum)
return checksum;
And here is our complete message that will be sent to machine:
Sting rts
priority + ‘+ sysDate + “iit + ordertype +";
logException("OrderMessae :* + retmsg);
retmsg = ProtocolASCISTX + retmsg + ProtocolASCI.CR + ProtocolASCILETX +
ProtocolMessage.getCheckSum(retmsg) + ProtocolASCILCR + ProtocolASCILLF;
30]1|" + rackld + ~*" + positionNumber + "** + sampleld + "all" + testlds +
Last but not least, | don't know what is the machine as I don't have manual but I sense that
you don't need to send every message one by one, You can send all at once
here is the code snippet of sending and receiving message to and from machine.
while (clientintMessage != ProtocolASCIlEOT) {
clientintMessage = infromClientreadd;
currentMsg += String valueOf(Character.toChars(clientintMessage));
1/ System out printin(currentMisg)
if (clientintMessage == ProtocolASCILENQ) (
outToClient writeBytes(“ + ProtocolASCILACK);
System out.printin("{ACk] on Analyzer [ENQ)");
} else if (clientintMessage == ProtocolASCILACK) {
System.out printin(*Analyzer [ACKI');
// Send your order message here
outToClientwriteBytes(retmsg):
)
} else if (clientintMessage
outToClient writeBytes(" + ProtocolASCILACK);
} else if (clientintMessage == ProtocolASCILNAK) {
System.out.printin(” Analyzer sent (NAK]
ProtocolASCILLF) {Where ProtocolASCII.ACK is \006', ProtocolASCII.ENQ is '\005' and ProtocolASCII.EOT is ‘\
004"
The code is pretty much self explanatory and | am using it in production.
Can you tell us which machine you are interfacing? It may help you if | have already integrated.
Thanks . If further assistance is required, let me know.
For your reference:
public class ProtocolASCll {
public static char STX = \002';
public static char ETX = O03)
public static char ETB = \027:
public static char EOT = \004’;
public static char ENQ = "\008';
public static char ACK
public static char NA\
public static char CR
public static char L
public static char MOR
public static char Fs
public static char GS
public static char RS.
public static char SFS = 027
public static char VT = 0x08; //END OF BLOCK 011
Update:
From your comments:
String retmsg = "3O|1|" + rackld + "4" + positionNumber + "A" + sampleld + "B|[" + testlds
+ |" + priority + "|" + sysDate + "|" + orderlype +"; Where testlds is the list of tests to
perform
example multitest order send 40|1||4%14
1234567848) AWBC\N* A ARBC\AAAAHGB\AAAAHCT\AA A AMCV\A AA AMCH\AA MICH
C\AAAAPLT\AA A ARDW-SD\A AA ARDW-CV\AAAAPDWAAAAAMPVAAA AAD.
LCRA AAAPCT\AAA ANEUTH\AAAALYMPHI\A AA AMONO#\A A AEOH\AAAABASOF\AAA AN
EUT%\9-** ALYMPH%\444SMONO%\A 44 AEOH\A AA ABASO\A AA ANRBCH\AAAANRBC%\
AAAAIGH\A AS AIG%IIIIINIIIIIIIIF
Get test codes from LIS manual or from company engineer and make pattern accordingly.Update 2
Socket clientSocket = null;
public static char STX =
public state char ETX
public static char £78 = \027'
public static char EOT = \o04;
public static char ENQ = \005';
public static char ACK = \006";
public static char NAK = "\025'
public static char CR = "\";
public static char LF = “\
public static char MOR = ">
\034y
public static char GS = \035"
public static char RS = "\036!
public static char SFS = \027"
public static char VT = 0x08; //END OF BLOCK 011
public static Vector vecMessages = new Vector 0;
private static int currentMsgCount
private static ServerSocket server;
public static char F
private static Socket connection;
Message mes = new Message);
public static void main(String args[)) throws IOExcepti
server = new ServerSocket(12221);
boolean stopped = false;
n, InterruptedException (
System .out.printin(” start.
connection = server.accept();
System out printin( wait for connection’);
BufferedReader inFromClient = new BufferedReader(new
InputStreamReader(connection.getinputStream0));
DataOutputStream outToClient ~ new DataOutputStream(connection.getOutputStream();
String currentNsg ="
int clientintMessage;
1) String I, 52, 83, $4, $5, 56 ="
J] 1 ="1H]@\\|ODM-Id(OGIWA.36]|GeneXpert_ PCAGeneXpert/4.glLis|P|1394-97]20070521100245" +
ProtocolASCILLF
J] + "PII" = ProtocolASCILLF
1] + *O|t|SI0-818)|**Testid-12[5|20070812140500]I[Al]ORHllIQ" + ProtocolASCULLF
W + "UIIF + ProtocolASCILLE;
MH s2= "Pht
1] 33 ="O}}|SID-818)|4**Testld-12)5|20070812140500)|AI]RHil 12
1] {fs = *Op|SiD-818||***Testid-14[5|20070812140600}IAIORMll
I I1s8 = "OBISID-818||4**Testld-16)5[20070812140700}lAllORHIillI@":
M36 = "UF
W
1] String retmsg
11 {MogException("OrderMessae :* + retmsa);
J] retmsg = ProtocolASCIISTX + retmsg + ProtocolASCILCR + PratocolASCILETX +
ProtocolMessage.getCheckSum(retmsg) + ProtocolASCIL.CR + ProtocolASCILLF,clientintMessage = inFromClient read;
/Jwbile (clientintMessage != ProtocolASCILEOT) (
while (true) {
while (clientintMessage != EOT) (
clientintMessage = inFromClientread);
currentMsg += String valueOf(Character.toChars(clientintMessage));
1/ System out printin(currentMsg);
if (clientintMessage == ENQ) {
outToClientwriteBytes(™ + ACK);
‘System.out printIn("[ACK] on Analyzer [ENQN*);
} else if (clientintMessage == ACK) {
System .outprintin("Analyzer(ACKI"};
if (vecMessages.sizeQ == currentMsgCount) (
vecMessages.clear(;
currentMsgCount = 0;
outToClientwriteBytes( + EOT);
System out printin(‘Host (E01);
else (
String msg = (String) vecMessages.get(currentMsgCount+ +);
outToClient writeBytes(msg);
uw System.out printin(’Msg " + msg substring(0, msglength0 - 4)
)
} else if (clientintMessage == LF) {
outToClient writeBytes( + ACK);
} else if (clientintMessage == NAK) (
System.out.printin(* Analyzer sent [NAK] °)
System out printin(currentMsg);
mes parser(currentMsg);
clientintMessage = 0;
currentMsg =";
)
1 connection.closed;
J! stopped = true:
)
public static class Message {
1] machine Send This Query
Query
1] HI@\|b4a88d9adab947a7b3dca2bS34119¢25]|ICU*GeneXpert™ o}lliLis|P|1394-97]20070521 100245,
/Qlt[PatientiD-556"SpecimentD-888}|]O@N.
We AAIN
6.3.2.1 Example of Upload Message ~ Instrument System Sends Hostpublic static Vector vecMessages = new VectorQ;
1 make message for machine
public String HeaderMessaged (
String retmsg = "HI@*\\lccc6ade20436233 4sffa3e287123 14aalLIIlICUAGeneXpert1.0])P|1394-
‘97/20070521100245";
1] SystemoutprintinC HeaderMessage :* + retmsg);
retmsg = STX + retmsg + CR + ETX + getCheckSum(retmsg) + CR + LF;
return retmsg;
)
yy it
// 63.133 Patient Information Record Find in Document and make it as per document
public String PatientMessage(Patient pat) ( //(Patient pat)
String retmsg = "P[il' + pat.getMRNOO + °|*" + pat.getPatientName( + "|" + pat.getDOBO +
“| + pat getGenderd) + *|Il]‘DrskM-LAS|lillll“SEAST
retmsg = STX + retmsg + CR + ETX + getCheckSum(retmsg) + CR + LF;
retum retmsg;
W 63.134 Test Order Record Find in Document
public String orderMessage(String samplela, String testids, String orderType, String rackld, String
positionNumber, String priority) (
DateFormat dateFormat = new SimpleDateFormat("yyyyMMddl4HmmSs");
String sysDate = dateFormat format(new Date():
String retmsg = “30)tI° + rackld + °" + positionNumber + "*" + sampleld + "al" + testids +
‘|’ + priority +" + sysDate + "Il" + orderType +“;
retmsg = SIX + retmsg + CR + ETX + getCheckSum(retmsg) + CR + LF;
return retmsg;
UJ 63.135 Message Terminator Record Find in Document
public String terminatorMessage(String type) (
String retmsg = "Ut" + type;
retmsg = STX + retmsg + CR + ETX + getCheckSum(retmsg) + CR + LF;
return retmsg;
public String getCheckSum(String msg) (
int sum = 0;
for (int = 0; 1 < msg.length0; i++) (
sum += msg.charAt();sum += 16; //edding CR and ETX AND ETB
sum = sum % 256;
String checksum = Integer.toHexString(sum).toUpperCased;
if (checksumJength0 == 1) {
checksum = "0" + checksum;
)
//System.outprintin("\n Check Sum is ="+checksum);
return checksum;
public void parser(String input) (
1 Use StringTokenizer for split or spit
if input.charAt(1) =
| input.charat(2) == "a9 (
1/QI1|PatientID-5564Specimen!D-88|O@N
Ww Split it and get information which machine send in Query Sampleld and other
String rackld = “get from Query to check document";
String positionNumber = "get rom Query to check document";
String sampleld = “get from Query to check document
W this FetchOrdersi(machineld, samplela);_// for dummy Sample Run
this.FetchOrders1(‘abe’, sampleld);
this setMesType("Q");
public void FetchOrders1 (String machineld, String sampleld) {
try
this vecMessages.add(HeaderMessage();
this vecMessages.add(PatientMessage(); //Define patient information
this.vecMessages.add(orderMessage(sampleld, “rackld’, “positionNumber",
this vecMessages.add(terminatorMessage(
} catch (Exception €) {
eprintStackTraced;
y
Sharelmprove this answerFollow edited Mar 14, 2018 at 11:32 answered Mar 13, 2018 at 13:20
& Muhammad Nadeem
1496
‘Thank you very much @Muhammad for your answer. 'm checking it to get the best. the machine I use is
the GeneXpert from cepheid.com used to do the molecular tests. Ill come back to you if| have any other
questions.— Anatole ABE Mar 13, 2078 at 13:42
Re Muhammad. | Know now about the checksum of my machine. You can find it description,
here fr.scribd,com/document/35022142'/... You said that | don't need to send every message one by one.
So do | have to create a concatenation of all parties, can you provide me one example fram your fourparts, because i see that retmsg_use only one part. This will help me to see if| have to include Ascii chars
Thank you very much. ~ Anatole ABE Mar 13, 2018 at 15:15
My" message should include a carriage return (CR) at the end of each string. It can be added
aa String in Java in this way: “\r’.
Furthermore, the byte array that you write to the outputstream should include the following in
“A this order: STX, frame number, message string (inclusive of the CR character mentioned earlier)
A ETX, two uppercase checksum characters, CR, LF.
a
The special ASCII characters (STX, ETX etc,) are mentioned
here: https://www.cs.cm ~pattis/15-1XX/common/handouts/ascihtm|