IHE和HL7。 PCD-01确认

时间:2014-11-06 12:49:48

标签: android tcp standards hl7

我正在尝试从监视器获取数据到Android应用程序,并且我已将IHE - PCD-01事务作为模型。

方案很简单,基于实现监视器和平板电脑之间的互连,监视器不断发送信息,应用程序正在监听。

但我不明白的是,如果我在每条消息后都需要确认。有没有人可以帮我这个?

2 个答案:

答案 0 :(得分:1)

TL; DR 是的,这里没什么特别的,支持MSH-15,MSH-16字段驱动的通常的HL7 ACK / NACK。
默认确认一切都是“更好”安全然后抱歉“


文件“IHE病人护理设备(PCD),技术框架,第2卷(PCD TF-2)交易,修订版1.0 - 最终文本,2011年8月12日”,http://www.ihe.net/technical_framework/upload/ihe_pcd_tf_vol2_ft_2011-08-12.pdf提供

  

..附录G“HL7实施说明”中描述了HL7确认(ACK)消息的通用静态定义。

  

G.1网络指南

     

HL7 2.6 标准未定义网络通信协议。从HL7 2.2开始,较低层协议的定义已移至“实施指南”,但不是HL7要求。 IHE框架提出了以下建议:

     
      
  1. 应用程序应使用HL7实施指南附录C中定义的最小下层协议。

  2.   
  3. 想要发送消息(启动事务)的应用程序将启动网络连接以启动事务。接收方应用程序将响应查询确认或响应,但不会在此网络连接上启动新事务

  4.         

    G.1.1确认模式

         

    致谢信息

         

    确认消息可以基于应用程序定义。但是,简单的通用确认消息(ACK)可以用于,其中应用程序未定义特殊消息(应用程序级别确认),在其他情况下如第2.9节所述, “邮件处理规则”。

         

    IHE PCD交易PCD-03支持“增强模式”确认。请参阅PCD-03事务以及B.1 MSH中的讨论 - 消息头部分和B.2 MSA - 消息确认部分

和文档“Health Level Seven,Version 2.6©2007,第2章:控制”来自“HL7消息传递标准版本2.6”包,可以从http://www.hl7.org/implement/standards/product_brief.cfm?product_id=185下载

  

2.9.2使用原始处理规则的消息响应

     

..太长了引用..

     

2.9.3使用增强确认的响应

     

..太长了引用..

取决于HL7消息中MSH-15 Accept Acknowledgement TypeMSH-16 Application Acknowledgment Type字段的值

HL7标准的上述章节包含您想要阅读和实施/支持的内容。

修改

简单地说,在HL7协议中,发送的每封邮件中,发件人可以通过标记邮件标题段中的相应字段来请求ACK收据。 IHE不会删除此规则,也不会强制执行任何其他规则,但可以在应用程序的基础上定义任何其他约定。正确的预期行为由HL7规范定义,为了使其正确并创建一致的实现(没有第三方隐藏的意外),您可能需要多次阅读(另请参阅Stack Overflow: How can I make my system HL7 certified?

例如,这就是HAPI库处理ACKing的方式,代码段来自http://sourceforge.net/p/hl7api/code/764/tree/tags/Root_REL_1_2/hapi-mvn/hapi-base/src/main/java/ca/uhn/hl7v2/protocol/impl/ProcessorImpl.java

/** 
 * @see ca.uhn.hl7v2.protocol.Processor#cycle(boolean)
 */
public void cycle(boolean expectingAck) throws HL7Exception {
    log.debug("In cycle({})", expectingAck);

    cleanReservations();
    cleanAcceptAcks();
    cleanReservedMessages();

    Transportable in = null;
    try {
        if (expectingAck) {
            in = tryReceive(myContext.getLocallyDrivenTransportLayer());
        } else {
            in = tryReceive(myContext.getRemotelyDrivenTransportLayer());
        }
    } catch (TransportException e) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {}
        throw e;
    }

    // log
    if (in != null) {
           log.debug("Received message: {}", in.getMessage());
    } else {
      log.debug("Received no message");
    }

    // If we have a message, handle it
    if (in != null) { 
        String acceptAckNeeded = null;
        // String appAckNeeded = null;
        String ackCode = null;
        String ackId = null;

        try {
            String[] fieldPaths = {"MSH-15", "MSH-16", "MSA-1", "MSA-2"};
            String[] fields = PreParser.getFields(in.getMessage(), fieldPaths);         
            acceptAckNeeded = fields[0];
            // appAckNeeded = fields[1];
            ackCode = fields[2];
            ackId = fields[3];
        } catch (HL7Exception e) {
            log.warn("Failed to parse accept ack fields in incoming message", e);
        }

        if (ackId != null && ackCode != null && ackCode.startsWith("C")) {
            long expiryTime = System.currentTimeMillis() + 1000 * 60;
            myAcceptAcks.put(ackId, new ExpiringTransportable(in, expiryTime));
        } else {
            AcceptAcknowledger.AcceptACK ack = AcceptAcknowledger.validate(getContext(), in);

            if ((acceptAckNeeded != null && acceptAckNeeded.equals(AL)) 
                || (acceptAckNeeded != null && acceptAckNeeded.equals(ER) && !ack.isAcceptable()) 
                || (acceptAckNeeded != null && acceptAckNeeded.equals(SU) && ack.isAcceptable())) {
                trySend(myContext.getRemotelyDrivenTransportLayer(), ack.getMessage());    
            }

            if (ack.isAcceptable()) {
                if (isReserved(ackId)) {

                    log.debug("Received expected ACK message with ACK ID: {}", ackId);

                    removeReservation(ackId);
                    long expiryTime = System.currentTimeMillis() + 1000 * 60 * 5;                
                    myAvailableMessages.put(ackId, new ExpiringTransportable(in, expiryTime));

                } else {

                    log.debug("Sending message to router");
                    Transportable out = myContext.getRouter().processMessage(in);
                    sendAppResponse(out);

                }
            } else {
                // TODO: should we do something more here? Might be nice to 
                // allow a configurable handler for this situation
                log.warn("Incoming message was not acceptable");
            }

        }
    } else {
        String transport = expectingAck ? " Locally driven " : "Remotely driven";
        log.debug("{} TransportLayer.receive() returned null.", transport);
    }

    sleepIfNeeded();

    log.debug("Exiting cycle()");
}

答案 1 :(得分:0)

谢谢你的回答:) 当然,最好使用ACK来确定接收方是否正在收到消息,但是如果强制要求或不使用PCD-01事务我想知道什么。

我已经阅读了你的文件,而我所理解的是ACK的使用取决于MSH-15和MSH-16字段的内容,但有以下信息:

  

想要发送消息(启动事务)的应用程序将启动网络连接以启动事务。接收方应用程序将响应查询确认或响应,但不会在此网络连接上启动新事务

据我所知,ACK仅在连接开始时而不是在每条消息之后,是不是?