如何编写 ASTM 框架并将其发送到医疗设备

Ana*_*ABE 2 java string checksum astm

我目前正在研究 ASTM 协议,以向医疗仪器发送订单测试请求。但是我无法正确地向设备发送消息。更明确地说,我想例如发送这些帧:

        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";
Run Code Online (Sandbox Code Playgroud)

这是我现在的做法:

    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);
            }

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我把它变成字节,然后一个字节一个字节地发送。

除了我没有看到接收端有任何变化。

根据@Muhammad Answer 更新

这就是我向 GeneXpert DX 系统发送订单所做的工作

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;
}}
Run Code Online (Sandbox Code Playgroud)

这是我从控制台得到的结果:

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... 
Run Code Online (Sandbox Code Playgroud)

DX是机器软件,LIS是主机。每当我尝试发送 ENQ 时,机器都会用 NAK 回答我。

更新 2
它似乎正在工作。但是现在 Windows 事件向我显示了一个错误,说明为什么我的记录订单没有出现在 GeneXpert DX 主机记录列表中。头记录已被首先发送。

遵循@Muhammad *UPDATE 2** 后的 Windows 事件日志

GeneXpert DX 状态

Muh*_*eem 7

在回答之前,让我们讨论一下双向的机器机制。

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";
Run Code Online (Sandbox Code Playgroud)

首先,查看上面的 String 消息,没有任何标签编号,因为到目前为止我所做的每台机器都需要Tag number。例如:

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
Run Code Online (Sandbox Code Playgroud)

因此,您必须为每个标签设置NUMBERING

其次,机器第一次发送以下查询:

1H|\^&|||CS-2500^^22029^^^CP^BV981798||||||||E1394-9711
2Q|1|000038^01^   0012365845B||^^^040^PT-INN\^^^050^APTT-FS|0|201803081227007F
3L|1|NF9
Run Code Online (Sandbox Code Playgroud)

在 Query(2Q) Tag、000038rack id、01rack sequence number、001H18074618sample id(从 Barcode 读取)中,可以从主机或机器供应商提供的 LIS 手册中验证更多信息。

第三,当我们收到此消息时,我们将为我上面描述的机器发送消息(在下面再次写),并带有额外的校验和信息。同样,这个校验和可以在主机或机器的 LIS 手册中找到。

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
Run Code Online (Sandbox Code Playgroud)

校验和计算示例。请注意,它可能因机器而异。

  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;
}
Run Code Online (Sandbox Code Playgroud)

这是我们将发送到机器的完整消息:

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;
Run Code Online (Sandbox Code Playgroud)

最后但并非最不重要的一点,我不知道机器是什么,因为我没有手册,但我觉得您不需要一一发送每条消息。您可以一次发送所有内容。

这是向机器发送消息和从机器接收消息的代码片段。

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] ");
                    }

                }
Run Code Online (Sandbox Code Playgroud)

其中ProtocolASCII.ACK'\006'ProtocolASCII.ENQ'\005'ProtocolASCII.EOT'\004'

该代码几乎是不言自明的,我正在生产中使用它。

你能告诉我们你连接的是哪台机器吗?如果我已经集成,它可能对你有帮助。

谢谢 。如果需要进一步的帮助,请告诉我。

供你参考:

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


}
Run Code Online (Sandbox Code Playgroud)

更新:

从你的评论:

String retmsg = "3O|1|" + rackId + "^" + positionNumber + "^" + sampleId + "^B||" + testIds + "|" + priority + "|" + sysDate + "|||||" + orderType + "";其中testIds是要执行的测试列表。

示例多测试订单发送 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

从 LIS 手册或公司工程师那里获取测试代码并相应地制作模式。

更新 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();
            }
        }

    }`
Run Code Online (Sandbox Code Playgroud)