文章
· 七月 19, 2023 阅读大约需 8 分钟

单机模式下 EMPI 的安装和适配 - FHIR之配置篇

在之前的文章中,我们已经了解了如何配置和自定义我们的 EMPI,我们已经了解了如何通过 HL7 消息传递将新患者纳入我们的系统中,但当然,并不是所有的东西都是 HL7 v.2!我们如何配置 EMPI 实例以使用 FHIR 消息传递?

什么是FHIR?

对于那些不太熟悉 FHIR 这个术语的人,只需指出它们是Fast Healthcare Interoperability Resource的首字母缩写即可。 FHIR是HL7制定的医疗保健互操作性标准,基于JSON格式和REST通信,建立了一系列不同类型信息(患者数据、医院中心、诊断、医疗预约......)的“资源”。您可以在他们的官方页面上查看所有这些资源

InterSystems 和 FHIR

从 InterSystems 中,我们了解到 FHIR 为医疗保健互操作性领域提供的实用程序,因此我们拥有广泛的产品和功能,使我们能够充分利用并发挥其全部潜力:

好吧,在我们的文章中,我们将利用适配器提供的功能来接收 FHIR 消息。

EMPI配置

FHIR 适配器安装

我们首先回顾一下独立 EMPI 安装中有哪些服务:

正如您所看到的,在独立模式下安装 EMPI 后,创建了一个注册表服务,其中包含配置 EMPI 所需的所有选项,以及我们称为 HSPIDATA 的命名空间,其中我们有一个产品来管理互操作性功能,需要。

对于我们的案例,我们创建了一个名为 WEBINAR 的新命名空间,我们将在其中部署正常的互操作性生产。我们将在此命名空间中安装FHIR 互操作性适配器,此安装将发布一个 Web 应用程序,我们将向该应用程序发送带有 FHIR 消息的 REST 调用。为此,我们将从终端执行以下命令:

 zn "WEBINAR" set status = ##class (HS.FHIRServer.Installer).InteropAdapterConfig( "/csp/healthshare/webinar/fhir/r4" )

安装后,我们将检查从管理门户创建的新应用程序:

让我们在 WEBINAR 命名空间中检查我们的生产:

默认创建了两个新的业务组件:

  1. InteropService :在我们的生产中,我们直接使用其类 HS.FHIRServer.Interop.Service 的名称,它将是负责接收发送到我们端点的 FHIR 消息的业务服务。 /csp/healthshare/网络研讨会/fhir/r4
  2. InteropOperation :我们已将此名称更改为 HS.FHIRServer.Interop.Operation。对于我们的示例,我们忽略了此业务操作,因为我们将通过 TCP 将 FHIR 消息的信息发送到我们的 EMPI 生产

创建业务组件来管理 FHIR 消息传递

很好,我们已经启用了业务服务来接收 FHIR 消息,现在我们感兴趣的是从消息中提取信息并将其发送到我们的 EMPI 生产。让我们看一下 HS.FHIRServer.Interop.Service 将接收的消息类型:

 Include HS.FHIRServer /// FHIRServer REST Business Service Class HS.FHIRServer.Interop.Service Extends (Ens.BusinessService, HS.HC.Util.Trace.Helper) { Parameter SETTINGS = "TargetConfigName:Basic:selector?context={Ens.ContextSearch/ProductionItems?targets=1&productionName=@productionId},Timeout:Basic" ; /// Configuration item to which to send inbound messages. Property TargetConfigName As Ens.DataType.ConfigName [ InitialExpression = "HS.FHIRServer.Interop.Operation" ] ; /// Timeout for dispatch (so we don't hold up the HTTP service too long or hang up a production shutdown). Property Timeout As %Integer [ InitialExpression = 25 ] ; /// Process an incoming message into the production; dispatch it to the configured target. /// The Interoperability contract requires that errors be returned as %Status here. Method OnProcessInput(pRequest As HS.FHIRServer.Interop.Request, Output pResponse As HS.FHIRServer.Interop.Response) As %Status

该消息的类型为 HS.FHIRServer.Interop.Request,如果我们查阅文档,我们将看到它有一个名为QuickStreamId的关联属性,我们将使用该属性来提取关联的 FHIR 消息。为此,我们将业务服务中收到的消息重定向到业务流程Webinar.BP.FHIRToHubRequest

该业务流程仅具有将消息重定向到负责通过 TCP 将消息发送到 EMPI 生产的业务操作FromFHIRToMPI的功能。

 Method OnRequest(pRequest As HS.FHIRServer.Interop.Request, Output pResponse As HS.FHIRServer.Interop.Response) As %Status { Set tSC = ..SendRequestSync ( "FromFHIRToMPI" , pRequest, .pResponse) Quit $$$OK }

让我们看一下Webinar.BO.ToMPI类,并解释它如何从 FHIR 获取消息并将其转换为我们将发送到 EMPI 生产的字符串:

 Include HS.FHIRServer Class Webinar.BO.ToMPI Extends Ens.BusinessOperation { Parameter ADAPTER = "EnsLib.TCP.CountedOutboundAdapter" ; Property Adapter As EnsLib.TCP.CountedOutboundAdapter ; Parameter INVOCATION = "Queue" ; Parameter SETTINGS = "FHIRMetadataSet::selector?context={HS.FHIRServer.Util.ContextSearch/FHIRMetadataSets}" ; /// FHIR Metadata Set. These are defined in HS_FHIRServer.FHIRMetadataSet. Property FHIRMetadataSet As %String (MAXLEN = 256 ) ; Method SendFHIRRequest(pRequest As HS.FHIRServer.Interop.Request, Output pResponse As HS.FHIRServer.Interop.Response) As %Status { // Get version of FHIR message configured Set tFHIRMetadataSetKey = $ZStrip ( $Piece ( ..FHIRMetadataSet , "/" , 1 ), "<>W" ) // We can have our FHIR message saved as a QuickStream or a Dynamic Object inside the json property of the request If pRequest.QuickStreamId'= "" { // Recover QuickStream of the FHIR message Set tQuickStream = ##class (HS.SDA3.QuickStream). %OpenId (pRequest.QuickStreamId) // Checking if message is in JSON format or XML If pRequest.Request.RequestFormatCode'= "" { Set tFHIRFormat = pRequest.Request.RequestFormatCode } Else { $$$ThrowOnError ( ##class (HS.HC.Util).GetFormatFromData(tQuickStream, .tFHIRFormat)) Do tQuickStream.Rewind() If tFHIRFormat= "json" { Set tFHIRFormat = $$$FHIRContentCodeJSON } ElseIf tFHIRFormat= "xml" { Set tFHIRFormat = $$$FHIRContentCodeXML } } // Transform QuickStream to DynamicObject Set tDynObj = ..GetDynObj (tQuickStream, tFHIRMetadataSetKey, tFHIRFormat) } ElseIf (( $IsObject (pRequest.Request.Json))&&(pRequest.Request.Json. %GetIterator (). %GetNext ())) { // Could have Json %DynamicObject if this host is called InProc. Set tDynObj = ..GetDynObj (pRequest.Request.Json, tFHIRMetadataSetKey) } Else { $$$ThrowStatus ( $$$ERROR ( $$$GeneralError , "FHIR interop request message missing FHIR content" )) } // Transform Dynamic Object to string set tRequest = tDynObj. %ToJSON () // Send message to EMPI production Set tSC= ..Adapter .SendMessageString(tRequest,.tResponse) $$$ThrowOnError (pRequest.NewResponse(.pResponse)) //Set pResponse.Response = ##class(HS.FHIRServer.API.Data.Response).%New() Set pResponse.Response.ResponseFormatCode = pRequest.Request.ResponseFormatCode set pResponse.Response.Status = 200 set pResponse.ContentType = "text/plain" Quit tSC } ClassMethod GetDynObj(stream As %Stream.Object , fhirVersion As %String , fhirFormat As %String ) As %DynamicObject { set schema = ##class (HS.FHIRServer.Schema).LoadSchema(fhirVersion) if fhirFormat = $$$FHIRContentCodeJSON { set dynObj = {}. %FromJSON (stream) } elseif fhirFormat = $$$FHIRContentCodeXML { set dynObj = ##class (HS.FHIRServer.Util.XMLToJSON).XMLToJSON(stream, schema) } Quit dynObj } XData MessageMap { <MapItems> <MapItem MessageType= "HS.FHIRServer.Interop.Request" > <Method>SendFHIRRequest</Method> </MapItem> </MapItems> } }

让我们一步步分析我们的类:

  1. 第一点是了解我们将在业务运营选项中配置的 FHIR 消息的版本。
     Set tFHIRMetadataSetKey = $ZStrip ( $Piece ( ..FHIRMetadataSet , "/" , 1 ), "<>W" )
    我们恢复正在处理的 FHIR 消息的类型,在我们的例子中它将是 R4。
  2. 接下来我们提取FHIR消息的内容:
     // We can have our FHIR message saved as a QuickStream or a Dynamic Object inside the json property of the request If pRequest.QuickStreamId'= "" { // Recover QuickStream of the FHIR message Set tQuickStream = ##class (HS.SDA3.QuickStream). %OpenId (pRequest.QuickStreamId) // Checking if message is in JSON format or XML If pRequest.Request.RequestFormatCode'= "" { Set tFHIRFormat = pRequest.Request.RequestFormatCode } Else { $$$ThrowOnError ( ##class (HS.HC.Util).GetFormatFromData(tQuickStream, .tFHIRFormat)) Do tQuickStream.Rewind() If tFHIRFormat= "json" { Set tFHIRFormat = $$$FHIRContentCodeJSON } ElseIf tFHIRFormat= "xml" { Set tFHIRFormat = $$$FHIRContentCodeXML } } // Transform QuickStream to DynamicObject Set tDynObj = ..GetDynObj (tQuickStream, tFHIRMetadataSetKey, tFHIRFormat) } ElseIf (( $IsObject (pRequest.Request.Json))&&(pRequest.Request.Json. %GetIterator (). %GetNext ())) { // Could have Json %DynamicObject if this host is called InProc. Set tDynObj = ..GetDynObj (pRequest.Request.Json, tFHIRMetadataSetKey) } Else { $$$ThrowStatus ( $$$ERROR ( $$$GeneralError , "FHIR interop request message missing FHIR content" )) }
  3. 我们从 FHIR 消息中获取 %DynamicObject:
     ClassMethod GetDynObj(stream As %Stream.Object , fhirVersion As %String , fhirFormat As %String ) As %DynamicObject { set schema = ##class (HS.FHIRServer.Schema).LoadSchema(fhirVersion) if fhirFormat = $$$FHIRContentCodeJSON { set dynObj = {}. %FromJSON (stream) } elseif fhirFormat = $$$FHIRContentCodeXML { set dynObj = ##class (HS.FHIRServer.Util.XMLToJSON).XMLToJSON(stream, schema) } Quit dynObj }
  4. 最后,我们将其转换为字符串,并通过 TCP 将其发送到我们的 EMPI 生产,向向我们发送原始消息的系统返回 200:
     // Transform Dynamic Object to string set tRequest = tDynObj. %ToJSON () // Send message to EMPI production Set tSC= ..Adapter .SendMessageString(tRequest,.tResponse) $$$ThrowOnError (pRequest.NewResponse(.pResponse)) //Set pResponse.Response = ##class(HS.FHIRServer.API.Data.Response).%New() Set pResponse.Response.ResponseFormatCode = pRequest.Request.ResponseFormatCode set pResponse.Response.Status = 200 set pResponse.ContentType = "text/plain" Quit tSC

好吧,我们已经将消息发送到我们的 EMPI 生产中。让我们看一下示例消息的跟踪:

在下一篇文章中,我们将检索提交的字符串,将其转换回 %DynamicObject 并向 EMPI 提供数据以使用新数据执行注册/更新操作。

希望这些内容对你有用!

致敬原创作者 @Luis Angel

讨论 (0)1
登录或注册以继续