I am currently working on the ASTM protocol to send orders tests request to medical instrument. But I cannot send a message to the equipment correctly. To be more explicit, I want for example to send these frames:
String h1, s2, s3, s4, s5, s6 = "";
h1 = "H|@^\\|ODM-IdfDGIWA-36|||GeneXpert PC^GeneXpert^4.8|||||LIS||P|1394-97|20070521100245";
s2 = "P|1";
s3 = "O|1|SID-818||^^^TestId-12|S|20070812140500|||||A||||ORH||||||||||Q";
s4 = "O|2|SID-818||^^^TestId-14|S|20070812140600|||||A||||ORH||||||||||Q";
s5 = "O|3|SID-818||^^^TestId-16|S|20070812140700|||||A||||ORH||||||||||Q";
s6 = "L|1|F";
and here is how I am doing now:
writeMeBytes(outToServer, h1.getBytes());
writeMeBytes(outToServer, s2.getBytes());
writeMeBytes(outToServer, s3.getBytes());
writeMeBytes(outToServer, s4.getBytes());
writeMeBytes(outToServer, s5.getBytes());
writeMeBytes(outToServer, s6.getBytes());
public static void writeMeBytes(DataOutputStream dos, byte [] b){
if (b.length >0){
int j = 0;
while (j <= b.length-1) {
try {
dos.write(b[j++]);
} catch (IOException ex) {
Logger.getLogger(SimpleServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
I 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 I 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.println(" start... ");
connection = server.accept();
System.out.println("wait for connection");
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connection.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connection.getOutputStream());
String currentMsg = "";
int clientIntMessage;
String h1, s2, s3, s4, s5, s6 = "";
h1 = "1H|@^\\|ODM-IdfDGIWA-36|||GeneXpert PC^GeneXpert^4.8|||||LIS||P|1394-97|20070521100245" + ProtocolASCII.LF
+ "P|1" + ProtocolASCII.LF
+ "O|1|SID-818||^^^TestId-12|S|20070812140500|||||A||||ORH||||||||||Q" + ProtocolASCII.LF
+ "L|1|F" + ProtocolASCII.LF;
s2 = "P|1";
s3 = "O|1|SID-818||^^^TestId-12|S|20070812140500|||||A||||ORH||||||||||Q";
//s4 = "O|2|SID-818||^^^TestId-14|S|20070812140600|||||A||||ORH||||||||||Q";
//s5 = "O|3|SID-818||^^^TestId-16|S|20070812140700|||||A||||ORH||||||||||Q";
s6 = "L|1|F";
String retmsg = h1;
//logException("OrderMessae :" + retmsg);
retmsg = ProtocolASCII.STX + retmsg + ProtocolASCII.CR + ProtocolASCII.ETX + ProtocolMessage.getCheckSum(retmsg) + ProtocolASCII.CR + ProtocolASCII.LF;
clientIntMessage = inFromClient.read();
//while (clientIntMessage != ProtocolASCII.EOT) {
while (true) {
currentMsg += String.valueOf(Character.toChars(clientIntMessage));
if (clientIntMessage == ProtocolASCII.ENQ) {
outToClient.writeBytes("" + ProtocolASCII.ACK);
System.out.println(" <--- LIS [ACK] on DX [ENQ]");
} else if (clientIntMessage == ProtocolASCII.ACK) {
System.out.println(" ---> DX [ACK]");
// Send your order message here
outToClient.writeBytes(retmsg);
} else if (clientIntMessage == ProtocolASCII.CR) {
System.out.println(currentMsg);
outToClient.writeBytes("" + ProtocolASCII.ACK);
} else if (clientIntMessage == ProtocolASCII.NAK) {
System.out.println(" ---> DX sent [NAK] ");
System.out.println(" --- LIS now wait 10 sec... ");
Thread.sleep(10000);
outToClient.writeBytes("" + ProtocolASCII.ENQ);
System.out.println(" <--- LIS [ENQ] ");
} else if (clientIntMessage == ProtocolASCII.EOT) {
System.out.println(" ---> DX END OF TRANSMISSION");
outToClient.writeBytes("" + ProtocolASCII.ENQ);
System.out.println(" <--- LIS [ENQ] ");
}
if (stopped) {
break;
}
clientIntMessage = inFromClient.read();
}
connection.close();
stopped = true;
}}
And this is the result I get from the console:
start...
wait for connection
<--- LIS [ACK] on DX [ENQ]
1H|@^\|ODM-rQTcjIWA-66||GeneXpert PC^GeneXpert^4.8|||||LIS||P|1394-97|20180314003724
Q|1|ALL||||||||||O@N
L|1|N
B5
---> DX [EOT]
<--- LIS [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.
Before answering, lets discuss machine mechanism for Bidirectional.
String h1, s2, s3, s4, s5, s6 = "";
h1 = "H|@^\\|ODM-IdfDGIWA-36|||GeneXpert PC^GeneXpert^4.8|||||LIS||P|1394-97|20070521100245";
s2 = "P|1";
s3 = "O|1|SID-818||^^^TestId-12|S|20070812140500|||||A||||ORH||||||||||Q";
s4 = "O|2|SID-818||^^^TestId-14|S|20070812140600|||||A||||ORH||||||||||Q";
s5 = "O|3|SID-818||^^^TestId-16|S|20070812140700|||||A||||ORH||||||||||Q";
s6 = "L|1|F";
First, viewing above String message, there isn't any tag numbering as every machine I have done so far requires Tag number. For example:
1H|\^&|||CS-2500^00-08^22029^^^CP^BV981798||||||||E1394-97
2P|1|||00000152556|^JOHN^ABC||19440601|M|||||^Dr.Shaukat Khanum Hospital|||||||||^^^EAST
3O|1|000038^01^0012586236^B||^^^051^^100.00¥^^^044^^100.00|R|201803081225236|||||N
4L|1|N
So, you must have NUMBERING for each tag.
Second, Machine sends following query at first time:
1H|\^&|||CS-2500^^22029^^^CP^BV981798||||||||E1394-9711
2Q|1|000038^01^ 0012365845B||^^^040^PT-INN\^^^050^APTT-FS|0|201803081227007F
3L|1|NF9
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 I have described above (writing again below) with additional checksum information. Again, this checksum can be found in host or LIS manual of machine.
1H|\^&|||CS-2500^00-08^22029^^^CP^BV981798||||||||E1394-97
2P|1|||00000152556|^JOHN^ABC||19440601|M|||||^Dr.Shaukat Khanum Hospital|||||||||^^^EAST
3O|1|000038^01^12345678^B||^^^051^^100.00¥^^^044^^100.00|R|201803081225236|||||N
4L|1|N
Example of Checksum calculation. Note that it may vary from machine to machine.
public static String getCheckSum(String msg) {
int sum = 0;
for (int i = 0; i < msg.length(); i++) {
sum += msg.charAt(i);
}
sum += 16; //adding CR and ETX AND ETB
sum = sum % 256;
String checksum = Integer.toHexString(sum).toUpperCase();
if (checksum.length() == 1) {
checksum = "0" + checksum;
}
//System.out.println("\n Check Sum is ="+checksum);
return checksum;
}
And here is our complete message that will be sent to machine:
String retmsg = "3O|1|" + rackId + "^" + positionNumber + "^" + sampleId + "^B||" + testIds + "|" + priority + "|" + sysDate + "|||||" + orderType + "";
logException("OrderMessae :" + retmsg);
retmsg = ProtocolASCII.STX + retmsg + ProtocolASCII.CR + ProtocolASCII.ETX + ProtocolMessage.getCheckSum(retmsg) + ProtocolASCII.CR + ProtocolASCII.LF;
Last but not least, I 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 != ProtocolASCII.EOT) {
clientIntMessage = inFromClient.read();
currentMsg += String.valueOf(Character.toChars(clientIntMessage));
// System.out.println(currentMsg);
if (clientIntMessage == ProtocolASCII.ENQ) {
outToClient.writeBytes("" + ProtocolASCII.ACK);
System.out.println("[ACK] on Analyzer [ENQ]");
} else if (clientIntMessage == ProtocolASCII.ACK) {
System.out.println("Analyzer [ACK]");
// Send your order message here
outToClient.writeBytes(retmsg);
}
} else if (clientIntMessage == ProtocolASCII.LF) {
outToClient.writeBytes("" + ProtocolASCII.ACK);
} else if (clientIntMessage == ProtocolASCII.NAK) {
System.out.println(" Analyzer sent [NAK] ");
}
}
Where ProtocolASCII.ACK is '\006'
, ProtocolASCII.ENQ is '\005'
and ProtocolASCII.EOT is '\004'
.
The code is pretty much self explanatory and I am using it in production.
Can you tell us which machine you are interfacing? It may help you if I have already integrated.
Thanks . If further assistance is required, let me know.
For your reference:
public class ProtocolASCII {
public static char STX = '\002';
public static char ETX = '\003';
public static char ETB = '\027';
public static char EOT = '\004';
public static char ENQ = '\005';
public static char ACK = '\006';
public static char NAK = '\025';
public static char CR = '\r';
public static char LF = '\n';
public static char MOR = '>';
public static char FS = '\034';
public static char GS = '\035';
public static char RS = '\036';
public static char SFS = '\027';
public static char VT = 0x0B; //END OF BLOCK 011
}
Update:
From your comments:
String retmsg = "3O|1|" + rackId + "^" + positionNumber + "^" + sampleId + "^B||" + testIds + "|" + priority + "|" + sysDate + "|||||" + orderType + "";
Where testIds is the list of tests to perform.
example multitest order send 4O|1||4^1^ 12345678^B|^^^^WBC\^^^^RBC\^^^^HGB\^^^^HCT\^^^^MCV\^^^^MCH\^^^^MCHC\^^^^PLT\^^^^RDW-SD\^^^^RDW-CV\^^^^PDW\^^^^MPV\^^^^P-LCR\^^^^PCT\^^^^NEUT#\^^^^LYMPH#\^^^^MONO#\^^^^EO#\^^^^BASO#\^^^^NEUT%\^^^^LYMPH%\^^^^MONO%\^^^^EO%\^^^^BASO%\^^^^NRBC#\^^^^NRBC%\^^^^IG#\^^^^IG%|||||||N||||||||||||||F
Get test codes from LIS manual or from company engineer and make pattern accordingly.
Update 2
Socket clientSocket = null;
public static char STX = '\002';
public static char ETX = '\003';
public static char ETB = '\027';
public static char EOT = '\004';
public static char ENQ = '\005';
public static char ACK = '\006';
public static char NAK = '\025';
public static char CR = '\r';
public static char LF = '\n';
public static char MOR = '>';
public static char FS = '\034';
public static char GS = '\035';
public static char RS = '\036';
public static char SFS = '\027';
public static char VT = 0x0B; //END OF BLOCK 011
public static Vector<String> vecMessages = new Vector<String>();
private static int currentMsgCount = 0;
private static ServerSocket server;
private static Socket connection;
Message mes = new Message();
public static void main(String args[]) throws IOException, InterruptedException {
server = new ServerSocket(12221);
boolean stopped = false;
System.out.println(" start... ");
connection = server.accept();
System.out.println("wait for connection");
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connection.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connection.getOutputStream());
String currentMsg = "";
int clientIntMessage;
// String h1, s2, s3, s4, s5, s6 = "";
// h1 = "1H|@^\\|ODM-IdfDGIWA-36|||GeneXpert PC^GeneXpert^4.8|||||LIS||P|1394-97|20070521100245" + ProtocolASCII.LF
// + "P|1" + ProtocolASCII.LF
// + "O|1|SID-818||^^^TestId-12|S|20070812140500|||||A||||ORH||||||||||Q" + ProtocolASCII.LF
// + "L|1|F" + ProtocolASCII.LF;
// s2 = "P|1";
// s3 = "O|1|SID-818||^^^TestId-12|S|20070812140500|||||A||||ORH||||||||||Q";
// //s4 = "O|2|SID-818||^^^TestId-14|S|20070812140600|||||A||||ORH||||||||||Q";
// //s5 = "O|3|SID-818||^^^TestId-16|S|20070812140700|||||A||||ORH||||||||||Q";
// s6 = "L|1|F";
//
// String retmsg = h1;
// //logException("OrderMessae :" + retmsg);
// retmsg = ProtocolASCII.STX + retmsg + ProtocolASCII.CR + ProtocolASCII.ETX + ProtocolMessage.getCheckSum(retmsg) + ProtocolASCII.CR + ProtocolASCII.LF;
clientIntMessage = inFromClient.read();
//while (clientIntMessage != ProtocolASCII.EOT) {
while (true) {
while (clientIntMessage != EOT) {
clientIntMessage = inFromClient.read();
currentMsg += String.valueOf(Character.toChars(clientIntMessage));
// System.out.println(currentMsg);
if (clientIntMessage == ENQ) {
outToClient.writeBytes("" + ACK);
System.out.println("[ACK] on Analyzer [ENQ]");
} else if (clientIntMessage == ACK) {
System.out.println("Analyzer [ACK]");
if (vecMessages.size() == currentMsgCount) {
vecMessages.clear();
currentMsgCount = 0;
outToClient.writeBytes("" + EOT);
System.out.println("Host [EOT]");
} else {
String msg = (String) vecMessages.get(currentMsgCount++);
outToClient.writeBytes(msg);
// System.out.println("Msg " + msg.substring(0, msg.length() - 4));
}
} else if (clientIntMessage == LF) {
outToClient.writeBytes("" + ACK);
} else if (clientIntMessage == NAK) {
System.out.println(" Analyzer sent [NAK] ");
}
}
System.out.println(currentMsg);
mes.parser(currentMsg);
clientIntMessage = 0;
currentMsg = "";
}
// connection.close();
// stopped = true;
}
public static class Message {
// machine Send This Query ==>6.3.2.1.5 Example of Upload Message – Instrument System Sends Host Query
// H|@^\|b4a88d9adab947a7b3dca2b534119c25||ICU^GeneXpert^1.0|||||LIS||P|1394-97|20070521100245
// Q|1|PatientID-556^SpecimenID-888||||||||||O@N
// L|1|N
public static Vector<String> vecMessages = new Vector<String>();
// make message for machine
public String HeaderMessage() {
String retmsg = "H|@^\\|ccc6ade20d3623314sffa3e287f2314ad||LIS|||||ICU^GeneXpert^1.0||P|1394-97|20070521100245";
// System.out.println("HeaderMessage :" + retmsg);
retmsg = STX + retmsg + CR + ETX + getCheckSum(retmsg) + CR + LF;
return retmsg;
}
// P|1
// 6.3.1.3.3 Patient Information Record Find in Document and make it as per document
public String PatientMessage(Patient pat) { //(Patient pat)
String retmsg = "P|1|||" + pat.getMRNO() + "|^" + pat.getPatientName() + "||" + pat.getDOB() + "|" + pat.getGender() + "|||||^Dr.SKM-LAS||||||||||||^^^EAST";
retmsg = STX + retmsg + CR + ETX + getCheckSum(retmsg) + CR + LF;
return retmsg;
}
// 6.3.1.3.4 Test Order Record Find in Document
public String orderMessage(String sampleId, String testIds, String orderType, String rackId, String positionNumber, String priority) {
DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmSS");
String sysDate = dateFormat.format(new Date());
String retmsg = "3O|1|" + rackId + "^" + positionNumber + "^" + sampleId + "^B||" + testIds + "|" + priority + "|" + sysDate + "|||||" + orderType + "";
retmsg = STX + retmsg + CR + ETX + getCheckSum(retmsg) + CR + LF;
return retmsg;
}
// 6.3.1.3.5 Message Terminator Record Find in Document
public String terminatorMessage(String type) {
String retmsg = "L|1|" + type;
retmsg = STX + retmsg + CR + ETX + getCheckSum(retmsg) + CR + LF;
return retmsg;
}
public String getCheckSum(String msg) {
int sum = 0;
for (int i = 0; i < msg.length(); i++) {
sum += msg.charAt(i);
}
sum += 16; //adding CR and ETX AND ETB
sum = sum % 256;
String checksum = Integer.toHexString(sum).toUpperCase();
if (checksum.length() == 1) {
checksum = "0" + checksum;
}
//System.out.println("\n Check Sum is ="+checksum);
return checksum;
}
public void parser(String input) {
// Use StringTokenizer for split or split
if (input.charAt(1) == 'Q' || input.charAt(2) == 'Q') {
//Q|1|PatientID-556^SpecimenID-888||||||||||O@N
// Split it and get information which machine send in Query SampleId and other
String rackId = "get from Query to check document";
String positionNumber = "get from Query to check document";
String sampleId = "get from Query to check document";
// this.FetchOrders1(machineId, sampleId); // for dummy Sample Run
this.FetchOrders1("abc", sampleId);
this.setMesType("Q");
}
}
public void FetchOrders1(String machineId, String sampleId) {
try {
this.vecMessages.add(HeaderMessage());
this.vecMessages.add(PatientMessage()); //Define patient information
this.vecMessages.add(orderMessage(sampleId, "test", "N", "rackId", "positionNumber", "R"));
this.vecMessages.add(terminatorMessage("N"));
} catch (Exception e) {
e.printStackTrace();
}
}
}`