Pesquisar

Artigo
· Set. 26 19min de leitura

A Configurable Template for Automated Splitting of HL7 Repeating Segments

Introduction

HL7 messages often contain multiple repeating segments such as NTE, AL1, OBX, ZTX, DG1, and others. These segments sometimes require individual processing and routing to different downstream systems. This technical paper introduces a configurable template designed to automate the splitting of these repeating HL7 segments, improving message handling and integration efficiency.

This template offers flexibility by allowing users to either send the message as-is with the required logic applied or split the message based on customizable settings defined within the business process configuration. Importantly, this approach supports reuse across various use cases and HL7 schemas.

Please note that you may need to update or modify a few lines of code depending on your HL7 schema or any custom schema you use. The source message must conform to your message schema.

Key configurable parameters include:

  • Message type selection
  • Identification of repeating segments
  • Segment group definitions
  • Unique identifier settings

Highlights:

  • The source message can contain multiple repeating segments such as NTE, AL1, OBX, etc.
  • You can send the entire message without splitting it, applying only your logic, to downstream systems.
  • Alternatively, you can split the message according to your instructions and send the segments separately to one or multiple downstream systems as needed.

This process is designed to split any repeating HL7 message segment and route it to the chosen downstream systems.  It functions as a reusable template, requiring little to no code modification to adapt to your specific needs.

The process provides dynamic configuration settings within the business process setup, allowing users to customize message splitting as needed. The main settings are detailed in Table 1 below:

Table 1: Process Settings – Configurations

SN

Setting Name

Short Description

Example

1.

MessageType 

HL7 message type used for splitting.

ADT^A01, ORU^01, DFT^P03 etc

2.

MultipleSegmentName

Repeating segment(s) in the HL7 message to be split individually. Specify the segment name that needs to be sent individually

NTE, OBX, ZTX, RXP, etc.

3.

IsRepeating

Confirms if the segment in #2 repeats. Only "Y" is currently supported (default is "Y").

Y or N

4.

SegmentRepeatingGrp

Indicates if the segment is part of a group (e.g., RXCgrp()). Nested groups like PIDgrp().NTE() are not supported here.

RXCgrp(), PIDgrp(),

 

5.

MultipleSegGrpPath

If #4 is "Y", define the path to the group. Can be selected from a list

Note: You can edit or update this according to your requirements by changing the code.
Be careful, it depends on your message schema. If you have a custom schema, please update it accordingly.

PIDgrp() → NTE(), PIDgrp() → OBX()
Select DropDownList: PIDgrp, MRGgrp, PRG1grp, IN1grp, ORCgrp(1).OBRuniongrp, PIDgrpgrp(1).ORCgrp(1).OBXgrp

6.

SegmentNameForUniqueID

Segment name to be used for generating a unique message identifier.

MHS or FT1grp

7.

SegmentDetails

Full segment path for inserting the value. Use the segment name if it's the same.

MSH,

FT1grp(1).FT1

8.

SegmentFieldNo

Field number where the unique value should be inserted. Use the instance number.

 

10 = (MSH:10 – Control id)

 2 = ( FT1grp(1).FT1.2 – Financial transaction id) 

9.

SeperationUniqueID 

Separator for the unique value (e.g., ".", "#", "-"). Appends a unique number to the field value.

., #, -, etc

For example, such as XXXXX.1, XXXXX.2, etc.

 

Usage Instructions

  1. Copy the provided code and create a new business process in the HealthConnect Management Portal using the code class.
  2. Navigate to Process → Settings, then select TargetConfigurations.

  1. Choose the operations and target systems where you want to send the message.
  2. Configure all settings as specified in the table above according to your requirements and apply the changes.
  3. Restart your process to activate the new configuration.

TESTING:

Screenshot 1: Management Portal showing sending the entire source HL7 message and sending repeating segments to three different systems.

Select à Process à Setting and complete all the configuration according to your requirements.

Screenshot 2.a: Process settings configuration screen.

If you need more information about any configuration, simply click the title for detailed explanations.

Screenshot 2.b: Supporting information screen.

Examples of Source and Target Messages:

Screenshot 3: Source message containing 5 repeating ZTX segments.

Screenshot 4.a: Target system configuration sending the source message as-is and splitting the ZTX segments individually to operations.

Screenshot 4.b: Target system sending the source message as-is and splitting only the last ZTX segment to operations.

Another example where only split messages are sent, without sending the original full message first:

Screenshot 5: Source message with two ZTX segments split into two separate messages, each containing one ZTX segment.

Screenshot 6: Source Message

Screenshot 7.a: Target message containing the first ZTX  segment.

Screenshot 7.b: Target message containing the second ZTX segment.

Additional Example with Different Configurations

In this example, the source message contains multiple repeating NTE segments, where each NTE segment is part of the group path: PIDgrpgrp().ORCgrp().OBXgrp.

The process is configured to split and send each NTE segment individually to the target system. The resulting target messages are shown below:

  • Screenshot 10.a – First NTE segment
  • Screenshot 10.b – Second NTE segment
  • Screenshot 10.c– Third NTE segment

Screenshot 8: Process Configurations

Screenshot 9: Source message

Screenshot 10.a: Target message – First NTE segment

Screenshot 10.b: Target message – Second NTE segment

Screenshot 10.c: Target message – Third NTE segment

CODE

/// This process reads the HL7 messages from the source, splits the messages according 
/// to the given segment, and forwards them to the specified router/system. 
/// For example, if the message has multiple OBX, NTE, or ZTX segments,each message will 
/// include only one of the given segments. Additionally, if required, it will make the 
/// message unique by adding the serial number to the given segment's field.
/// <br>
///  This is a template that can be reused without modification in the code or with minimal modification based on the requirements. 
/// <br/> 
/// <br><b>Author: Sanjib Pandey</b>
/// Version:1.0
/// Date : 25/09/2025
/// <br>
Class SANJIB.Process.SegmentSplitAndSendMessage Extends Ens.BusinessProcess [ ClassType = persistent ]
{

/// The descriptions of the datasets:
/// <ul>
/// <li>Message Type - Type of HL7 Message </li>
/// <li>Multiple Segment Names - Segment Name. </li>
/// <li>Is Repeating - Defines whether the segment given above is repeating or not.</li>
/// <li>Segment Repeating Group - Defines whether the segment is part of a repeating group or not, e.g., RXCgrp(), and not part of multiple or nested groups.</li>
/// <li>Multiple Segment Group Path - define and give the path if segment is multiple group eg PIDgrp->OBX()</li>
/// <li>Segment Name for Unique ID - Specifies the segment for the message's unique ID eg. MSH, FT1.</li>
/// <li>Segment Details - Specifies the segment path details with the field name for the message's unique ID, e.g., MSH, FT1grp(1).FT1.</li>
/// <li>Segment Field No - Specifies the field name where the unique ID should be placed.</li>
/// </ul>
/// Provide the message type, e.g., ADT^A01, DFT^P03.
Property MessageType As %String(MAXLEN = 10);
/// Specify the segment name that needs to be sent individually (e.g., ZTX, RXP, etc.)
Property MultipleSegmentName As %String(MAXLEN = 20);
/// Are the selected multiple segments (MulSegmentName) repeating or not? [Y, N], e.g., OBX(), ZTX(), NTE(). 
/// Note: Currently, only the "Y" part is implemented. By default, it is set to "Y".
Property IsRepeating As %String(VALUELIST = ",Y,N") [ InitialExpression = "Y", Required ];
/// Define if this segment is part of any other group [Y, N]. It should be something like "RXCgrp()",
/// but not part of multiple or nested groups, e.g., PIDgrp()-NTE().
Property SegmentRepeatingGrp As %String(VALUELIST = ",Y,N") [ InitialExpression = "N", Required ];
/// Define and provide the path if a segment has come from nested groups.</li>
/// Define the segment path if a repeating segment consists of another repeating group segment, 
/// e.g., PIDgrp() → NTE(), PIDgrp() → OBX(), PIDgrp() → AL1(). 
/// Currently, this might be suitable for Merge or Move Message e.g. A38, A40, A41, A42, A45 etc and other types of message. 
/// PIDgrpgrp(1)->ORCgrp(1)->OBXgrp(1), ORCgrp(1).OBRuniongrp.NTE() 
/// <br>
/// Note: The following is included but some of them has not been tested yet; it will be included in the new version (working on):
/// <ul>
/// <li>PIDgrpgrp(1)->ORCgrp(1)->OBXgrp(1)->any repeating group segment</li>
/// <li>ORCgrp(1).OBRuniongrp.any repeating group segment </li>
/// <li>RGSgrp(1).AISgrp(1).any repeating group segment?</li>
/// <li>RGSgrp(1).AIGgrp(1).any repeating group segment?</li>
/// <li>RGSgrp(1).AILgrp(1).any repeating group segment?</li>
/// </ul>
/// Multiple Segment Group Path - define and give the path if segment is multiple group eg PIDgrp->OBX()
/// PIDgrp(1).ORCgrp(1).OBXgrp(1).NTE() = PIDgrp(1).ORCgrp(1).OBXgrp (the last segment doesn't need to be mentioned (1)).
Property MultipleSegGrpPath As %String(VALUELIST = ",NA,PIDgrp,MRGgrp,PRG1grp,IN1grp,ORCgrp(1).OBRuniongrp,PIDgrpgrp(1).ORCgrp(1).OBXgrp,The following requires more testing — do not select or use in production!,ORCgrp(1).OBRuniongrp.OBXgrp,RGSgrp(1).AILgrp,RGSgrp(1).AIGgrp,RGSgrp(1).AISgrp") [ InitialExpression = "NA", Required ];
/// To make the message unique, please specify which segment and field you want to use, e.g., MHS or FT1.
Property SegmentNameForUniqueID As %String(MAXLEN = 5);
/// Provide the full segment path to insert the value. If it is the same as the segment name, use the same name here, e.g., MSH, FT1grp(1).FT1.
Property SegmentDetails As %String(MAXLEN = 50);
/// Which field do you want to put the unique number in? For example, MSH:10 (control ID) 
/// or FT1.2 (financial transaction ID). You are required to specify the field 
/// instance number. If you want to use the existing MSH control ID field, enter 10.
Property SegmentFieldNo As %String(MAXLEN = 2);
/// Separation of the unique value: For example, if you want to use MSH:10, 
/// the existing value of MSH:10 will be used, and an additional unique number will be 
/// automatically added by the program, such as XXXXX.1, XXXXX.2, etc.
Property SeperationUniqueID As %String(MAXLEN = 2);
/// Target Configuration Name
Property TargetConfigurations As Ens.DataType.ConfigName(MAXLEN = 100) [ Required ];
Parameter SETTINGS = "MessageType,MultipleSegmentName,IsRepeating,SegmentRepeatingGrp,MultipleSegGrpPath,SegmentNameForUniqueID,SegmentDetails,SegmentFieldNo,SeperationUniqueID,TargetConfigurations:Basic:selector?multiSelect=1&context={Ens.ContextSearch/ProductionItems?targets=1&productionName=@productionId}";
Method OnRequest(pRequest As EnsLib.HL7.Message, Output pResponse As Ens.Response) As %Status
{
 /* ----------------------------------------------------------------------------------------------
   Note: You can access user-defined data directly from the management portal settings. However, 
   for business requirements, you may need to manipulate or further check the data. In such cases,
   it’s better to assign the data to a local variable. For example, while you can select multiple 
   target configurations in the portal, some business logic may require sending the message to a 
   specific operation, router, or process. All of this can be controlled here.
   ...............................................................................................	*/
   S tSC = $$$OK
   //Let's clear the memory variable and get all user-defined datasets
   S (msgType,mulSeg,isRepeat,segRepGrp,mulSegGrpPath,segNameUID,segFieldNo,sepUID,tgtConfig)=""
   S msgType =..MessageType
   S mulSeg=..MultipleSegmentName
   S isRepeat=..IsRepeating
   S segRepGrp=..SegmentRepeatingGrp
   S mulSegGrpPath=..MultipleSegGrpPath
   S segNameUID=..SegmentNameForUniqueID
   S segDetail=..SegmentDetails
   S segFieldNo=..SegmentFieldNo
   S sepUID=..SeperationUniqueID
   S tgtConfig=..TargetConfigurations
   K messageType S messageType=pRequest.GetValueAt("MSH:9")
   K cpyMsg S cpyMsg = pRequest.%New()
   S cpyMsg =pRequest.%ConstructClone()
   S (segIdx,totSegment)=0
   Try
   { 
      #dim totSegment=pRequest.SegCount
      F i=1:1:totSegment
      {
         K segName S segName = pRequest.GetSegmentAt(i).Name
         I (segName = mulSeg)
          {
            S segIdx=i
            /*-----------------------------------------------------------------------------------
              Note:
               The following line of code is only required if you want to send the original message to another downstream system or perform interface transformation. Otherwise, it is not needed and can be deleted or commented out:
               [S tSC=..ProcessMessage(pRequest,tgtConfig)]
               This line is included here for testing purposes only.. 
            ------------------------------------------------------------------------------------*/
            //S tSC=..ProcessMessage(pRequest,tgtConfig) 
            Q
         }
      }
      //checking necessry datasets
      I ((msgType="" ) || (mulSeg="")||(isRepeat="")|| (segRepGrp=""))
      {
         S tSC=$system.Status.Error(5001,"Empty fields. Please check the MessageType, MultipleSegmentName, IsRepeating, SegmentRepeatingGrp,multipleSegGrpPath in the Process Settings at the Management Portal.")
      }
      elseif messageType=msgType
      {
         I ((isRepeat= "Y") && (segRepGrp="N")&& (mulSegGrpPath="NA") && (segIdx >0))  
         {	
            S tSC=..ProcessMessageFromNoRepeatGroup(cpyMsg,msgType,mulSeg,isRepeat,segRepGrp,segNameUID,segDetail,segFieldNo,sepUID,segIdx,tgtConfig)
         }
         elseif ((isRepeat= "Y") && (segRepGrp="Y") && (mulSegGrpPath="NA") && (segIdx >0))
         {
            S tSC=..ProcessMessageFromRepeatingGroup(cpyMsg,msgType,mulSeg,isRepeat,segRepGrp,segNameUID,segDetail,segFieldNo,sepUID,segIdx,tgtConfig)
         }
         elseif ((isRepeat = "Y") && (mulSegGrpPath '="") && (segIdx >0))
         {
            S tSC=..ProcessMessageFromRepeatingGroupPath(cpyMsg,msgType,mulSeg,isRepeat,segRepGrp,mulSegGrpPath,segNameUID,segDetail,segFieldNo,sepUID,segIdx,tgtConfig)
         }
         else
         {
            S tSC=..ProcessMessage(pRequest,tgtConfig)	
         }
      }
   }
   catch ErException
   {
      S tSC=ErException.AsStatus()
      $$$TRACE("Exception :"_tSC)	
   }
   Q tSC
}

/// The following method splits, processes, and sends the message only from the given repeating segment.
Method ProcessMessageFromNoRepeatGroup(ByRef mRequest As EnsLib.HL7.Message, msgType As %String, mulSeg As %String, isRepeat As %String, segRepGrp As %String, segNameUID As %String, segDetail As %String, segFieldNo As %Integer, sepUID As %String, segIdx As %Integer, tgtConfig As %String) As %Status
{
   S tSC = $$$OK
   Try
   {
      K totSeg 
      #dim totSeg = mRequest.SegCount
      //prepare dataset
      S dataSets=..GetDataSets(mRequest,segNameUID,segDetail,segFieldNo)
      K flag S msgUID=$P(dataSets,":",1)
      K flag S flag=$P(dataSets,":",2)
      I sepUID="" S sepUID="-"
      K totRepSeg S totRepSeg=mRequest.GetValueAt(mulSeg_"(*)")
      I (totRepSeg >1)
      {
         F j=1:1:totRepSeg
         {
            K newMsg S newMsg=##class(EnsLib.HL7.Message).%New()
            S newMsg.DocType=mRequest.DocType
            I ((segNameUID="MSH") && (flag="G"))
            {
               D newMsg.SetSegmentAt(mRequest.FindSegment("MSH"),1)
               D newMsg.SetValueAt(msgUID_sepUID_j,"MSH:"_segFieldNo)
            }
            else
            {
               D newMsg.SetSegmentAt(mRequest.FindSegment("MSH"),1)
            }
            F k=1:1:totSeg
            {
               K segName S segName = mRequest.GetSegmentAt(k).Name
               I (segName '= "MSH") && (segName '= mulSeg) 
               {
                  K getSegment S getSegment=mRequest.FindSegment(segName,,.sc)
                  I $ISOBJECT(getSegment)
                  {
                     I ((segName=segNameUID) && (flag ="G"))
                        {
                           D newMsg.AppendSegment(getSegment)
                           D newMsg.SetValueAt(msgUID_sepUID_j,segDetail_":"_segFieldNo) 
                        }
                        else
                        {
                           D newMsg.AppendSegment(getSegment)
                        }
                  }
                  else
                  {
                     s tSC=$system.Status.Error(5001,"Not found "_segName_"Segment")
                  }
               }
            }
            S addSeg=mRequest.GetSegmentAt(mulSeg_"("_j_")")
            D newMsg.InsertSegmentAt(addSeg,segIdx)
            $$$QuitOnError(..ProcessMessage(newMsg,tgtConfig))
            K addSeg
         }
      }
      else
      {
         S tSC=..ProcessMessage(mRequest,tgtConfig)
      }
   }
   catch ErException
   {
      S tSC=ErException.AsStatus()
      $$$TRACE("Exception :"_tSC)	
   }
   Q tSC
}

/// The following method splits, processes, and sends the message only from the given repeating group segment.
Method ProcessMessageFromRepeatingGroup(ByRef pRequest As EnsLib.HL7.Message, msgType As %String, mulSeg As %String, isRepeat As %String, segRepGrp As %String, segNameUID As %String, segDetail As %String, segFieldNo As %Integer, sepUID As %String, segIdx As %Integer, tgtConfig As %String) As %Status
{
   S tSC = $$$OK
   Try
   {
      K totSeg 
      #dim totSeg = pRequest.SegCount
      S dataSets=..GetDataSets(pRequest,segNameUID,segDetail,segFieldNo)
      K flag S msgUID=$P(dataSets,":",1)
      K flag S flag=$P(dataSets,":",2)
      I sepUID="" S sepUID="-"
      K totRepSeg S totRepSeg=pRequest.GetValueAt(mulSeg_"grp(*)")
      I (totRepSeg >1)
      {
         F j=1:1:totRepSeg
         {
            K newMsg S newMsg=##class(EnsLib.HL7.Message).%New()
            S newMsg.DocType=pRequest.DocType
            I ((segNameUID="MSH") && (flag="G"))
            {
               D newMsg.SetSegmentAt(pRequest.FindSegment("MSH"),1)
               D newMsg.SetValueAt(msgUID_sepUID_j,"MSH:"_segFieldNo)
            }
            else
            {
               D newMsg.SetSegmentAt(pRequest.FindSegment("MSH"),1)
            }
            F k=1:1:totSeg
            {
               K segName S segName = pRequest.GetSegmentAt(k).Name
               I (segName '= "MSH") && (segName '= mulSeg) 
               {
                  K getSegment S getSegment=pRequest.FindSegment(segName,,.sc)
                  I $ISOBJECT(getSegment)
                  {
                     I ((segName=segNameUID) && (flag ="G"))
                        {
                           D newMsg.AppendSegment(getSegment)
                           D newMsg.SetValueAt(msgUID_sepUID_j,segDetail_":"_segFieldNo) 
                        }
                        else
                        {
                           D newMsg.AppendSegment(getSegment)
                        }
                  }
                  else
                  {
                     S tSC=$system.Status.Error(5001,"Not found "_segName_"Segment")
                  }
               }
            }
            S addSeg=pRequest.GetSegmentAt(mulSeg_"grp("_j_")."_mulSeg)
            D newMsg.InsertSegmentAt(addSeg,segIdx)
            $$$QuitOnError(..ProcessMessage(newMsg,tgtConfig))	
            K addSeg 
         }
      }
      else
      {
         S tSC=..ProcessMessage(pRequest,tgtConfig)	
      }
   }
   catch ErException
   {
      S tSC=ErException.AsStatus()
      $$$TRACE("Exception :"_tSC)	
   }
   Q tSC
}

/// The following method splits, processes, and sends the message only from the specified group segments, e.g., PIDgrp().NTE(), ORCgrp(1).OBRuniongrp.NTE(), etc.
Method ProcessMessageFromRepeatingGroupPath(ByRef pRequest As EnsLib.HL7.Message, msgType As %String, mulSeg As %String, isRepeat As %String, segRepGrp As %String, mulSegGrpPath As %String, segNameUID As %String, segDetail As %String, segFieldNo As %Integer, sepUID As %String, segIdx As %Integer, tgtConfig As %String) As %Status
{
   // This method is not fully completed yet, it's still a work in progress. 
   // But whatever existing features are here are working.
   S tSC = $$$OK
   Try
   {   
      K totSeg 
      #dim totSeg = pRequest.SegCount
      S dataSets=..GetDataSets(pRequest,segNameUID,segDetail,segFieldNo)
      K flag S msgUID=$P(dataSets,":",1)
      K flag S flag=$P(dataSets,":",2)
      I sepUID="" S sepUID="-"
      S mulSegPathType=0
      I mulSegGrpPath="ORCgrp(1).OBRuniongrp"
      {
         S totRepSeg=pRequest.GetValueAt(mulSegGrpPath_"."_mulSeg_"(*)")
         S mulSegPathType=1
      }
      else
      {
         S totRepSeg=pRequest.GetValueAt(mulSegGrpPath_"(1)."_mulSeg_"(*)")
         S mulSegPathType=2
      }
      I (totRepSeg >1)
      {
         F j=1:1:totRepSeg
         {
            K newMsg S newMsg=##class(EnsLib.HL7.Message).%New()
            S newMsg.DocType=pRequest.DocType
            I ((segNameUID="MSH") && (flag="G"))
            {
               D newMsg.SetSegmentAt(pRequest.FindSegment("MSH"),1)
               D newMsg.SetValueAt(msgUID_sepUID_j,"MSH:"_segFieldNo)
            }
            else
            {
               D newMsg.SetSegmentAt(pRequest.FindSegment("MSH"),1)
            }
            F k=1:1:totSeg
            {
               K segName S segName = pRequest.GetSegmentAt(k).Name
               I (segName '= "MSH") && (segName '= mulSeg) 
               {
                  K getSegment S getSegment=pRequest.FindSegment(segName,,.sc)
                  I $ISOBJECT(getSegment)
                  {
                     I ((segName=segNameUID) && (flag ="G"))
                     {
                        D newMsg.AppendSegment(getSegment)
                        D newMsg.SetValueAt(msgUID_sepUID_j,segDetail_":"_segFieldNo) 
                     }
                     else
                     {
                        D newMsg.AppendSegment(getSegment)
                     }
                  }
                  else
                  {
                     s tSC=$system.Status.Error(5001,"Not found "_segName_"Segment")
                  }
               }
            }
            I mulSegPathType=1
            {
               S addSeg=pRequest.GetSegmentAt(mulSegGrpPath_"."_mulSeg_"("_j_")")
            }
            I mulSegPathType=2
            {
               S addSeg=pRequest.GetSegmentAt(mulSegGrpPath_"(1)."_mulSeg_"("_j_")")
            }
            D newMsg.InsertSegmentAt(addSeg,segIdx)
            $$$QuitOnError(..ProcessMessage(newMsg,tgtConfig))	
            K addSeg
         }
      }
      else
      {
         S tSC=..ProcessMessage(pRequest,tgtConfig)		
      }
   }
   catch ErException
   {
      S tSC=ErException.AsStatus()
      $$$TRACE("Exception :"_tSC)	
   }
   Q tSC
}

/// The following method retrieves the existing source message ID from the given location to create a new unique message ID for the new message (repeating segment).
Method GetDataSets(ByRef pRequest As EnsLib.HL7.Message, segNameUID As %String, segDetail As %String, segFieldNo As %Integer, pOutput As %Integer = 0, flag As %String = "R") As %Status
{
   S tSC=$$$OK
   Try
   {
      I $ISOBJECT(pRequest)
      {
         K msgUID
         I (segNameUID '="" && segDetail '= "" && segFieldNo '="")
         {
            S msgUID = pRequest.GetValueAt(segDetail_":"_segFieldNo)
            I (msgUID =""){S msgUID=0}
            S flag="G"
            S pOutput=msgUID
         }
      }
      else
      {
         S tSC=$system.Status.Error(5001,"Not a valid HL7 message!")
      }
   }
   catch Exception
   {
      S tSC=Exception.AsStatus()
   }
   Q pOutput_":"_flag
}

/// The following sends or processes the message to the selected target names in the management portal.
Method ProcessMessage(pMessage As EnsLib.HL7.Message, TargetList As %String) As %Status
{
   S tSC=$$$OK
   Try
   {
      I $ISOBJECT(pMessage)
      {
         For i=1:1:$L(TargetList,",") 
         {
            S tSC=..SendRequestAsync($P(TargetList,",",i),pMessage,0)	
         }
      }
   }
   catch ErException
   {
      S tSC=ErException.AsStatus()
   }
   Q tSC
}

Method OnResponse(request As Ens.Request, ByRef response As Ens.Response, callrequest As Ens.Response, callresponse As Ens.Response, pCompletionKey As %String) As %Status
{
   Quit $$$OK
}

Storage Default
{
<Data name="SegmentSplitAndSendMessageDefaultData">
<Subscript>"SegmentSplitAndSendMessage"</Subscript>
<Value name="1">
<Value>MessageType</Value>
</Value>
<Value name="2">
<Value>MultipleSegmentName</Value>
</Value>
<Value name="3">
<Value>IsRepeating</Value>
</Value>
<Value name="4">
<Value>SegmentRepeatingGrp</Value>
</Value>
<Value name="5">
<Value>MultipleSegGrpPath</Value>
</Value>
<Value name="6">
<Value>SegmentNameForUniqueID</Value>
</Value>
<Value name="7">
<Value>SegmentDetails</Value>
</Value>
<Value name="8">
<Value>SegmentFieldNo</Value>
</Value>
<Value name="9">
<Value>SeperationUniqueID</Value>
</Value>
<Value name="10">
<Value>TargetConfigurations</Value>
</Value>
</Data>
<DefaultData>SegmentSplitAndSendMessageDefaultData</DefaultData>
<Type>%Storage.Persistent</Type>
}

}

 

You can also download the code from the GitHub  

I hope this template will help streamline your HL7 message processing. If you have any questions or need further assistance, please feel free to ask.

Thank you.

3 Comments
Discussão (3)2
Entre ou crie uma conta para continuar
Artigo
· Set. 26 3min de leitura

SentinelIRIS

 

Building a Sensor Data Demo with Spring Boot and InterSystems IRIS

In the era of IoT and connected devices, sensor data is everywhere—tracking temperature in logistics, monitoring equipment performance, or recording environmental conditions. But capturing, storing, and analyzing this data in real time requires more than just hardware sensors.

It’s a practical example that combines Spring Boot, InterSystems IRIS, and a simple sensor simulation script to show how sensor data can flow from generation to storage and alerting.

Basically, the idea of ​​this project is to show all the integration capacity of IRIS with JAVA, where we can create a lightweight, high-performance and high-impact application.


What the Project Does

At its core, the repository demonstrates an end-to-end workflow:

  1. Sensor Simulation
    A Python script (simulate_sensor.py) generates realistic temperature, humidity, and location data. This removes the need for physical devices while testing the pipeline. (Not working very well yet!)
  2. Backend with Spring Boot
    A Java application built with Spring Boot receives sensor data through REST APIs, processes it, and persists it into the database.
  3. Database with InterSystems IRIS
    IRIS acts as the high-performance data store, with an initialization script (init.sql) to create tables and structure for historical analysis and alerting.

This setup mimics real-world use cases like cold-chain logistics, smart city monitoring, or industrial IoT systems.


Tech Stack Overview

Component Role
Spring Boot (Java 17) Core backend service for receiving and processing sensor data
Python Script Sensor simulator that pushes test data to the backend
InterSystems IRIS Database for storage and historical queries
Gradle + Docker Build and deployment tooling

Together, these pieces form a complete demo environment—simple to spin up locally, yet close enough to a production architecture to be a solid learning tool.


Why It’s Interesting

  • End-to-end clarity
    Many tutorials focus only on one layer. This repo shows the full pipeline, from data generation to storage.
  • Realistic scenario
    The simulated data includes environmental metrics often used in logistics and monitoring.
  • IRIS integration
    Instead of using a traditional database, the project leverages InterSystems IRIS, known for its performance and ability to handle time-series data.

Room for Improvement

While the project works well as a demo, there are opportunities to make it more robust:

  • API Documentation: Adding Swagger/OpenAPI would help developers understand and test endpoints easily.
  • Testing: Unit and integration tests could validate edge cases, such as data outside safe thresholds.
  • Security: Credentials are currently hardcoded. Introducing environment variables or a secrets manager would improve best practices.
  • Deployment: A Docker Compose setup would allow one-command startup of both the backend and IRIS.
  • Visualization: A simple dashboard could make the data and alerts more tangible for end users.

Real-World Applications

This kind of architecture can be applied across industries:

  • Logistics & Cold Chain – monitor goods in transit and alert if temperature deviates.
  • Smart Cities – track air quality, noise, or traffic patterns.
  • Industrial IoT – analyze machinery telemetry for predictive maintenance.
  • Healthcare – monitor environmental conditions in labs or hospitals.

The repo provides a blueprint: swap out the simulator for real sensors, enhance the backend logic, and you’re on the way to a production system.


Conclusion

The demo repository was coded by @Cecilia Valim and is more than just a toy project—it’s a practical showcase of how to handle sensor data with modern tools. By combining Spring Boot, Python, and InterSystems IRIS, it provides a clear, reproducible example of IoT data pipelines in action.

Whether you’re learning Spring Boot, exploring IRIS, or prototyping an IoT project, this repo is a great place to start.


👉 You can explore the full project here: github.com/cissavalim/demo

Discussão (0)1
Entre ou crie uma conta para continuar
Anúncio
· Set. 26

Édition d'automne : découvrez de nouvelles récompenses passionnantes sur Global Masters

Bonjour la communauté !

🍂 Les récompenses d'automne sont arrivées sur Global Masters !

Découvrez la saison avec nos nouvelles récompenses : c'est le moment idéal pour explorer la section Récompenses et obtenir vos récompenses préférées !

N'oubliez pas que la disponibilité des récompenses varie selon les régions. Vérifiez donc les offres disponibles dans votre région.

Ne manquez pas ces gourmandises de saison !

Vous n'êtes pas encore membre de Global Masters ? Inscrivez-vous ici avec vos identifiants SSO InterSystems.

Discussão (0)1
Entre ou crie uma conta para continuar
Pergunta
· Set. 26

Future Property Auctions: Unlocking Opportunities with Property Buy Rent UK

The UK property market is evolving quickly, and buyers and sellers are increasingly seeking faster and more transparent ways to complete transactions. One area gaining significant attention is future property auctions. These auctions provide speed, certainty, and competitive opportunities that traditional property sales often cannot match. At Property Buy Rent UK, we help clients prepare for upcoming auctions to ensure they achieve the best outcomes.

What Are Future Property Auctions?

Future property auctions are scheduled sales where properties are sold to the highest bidder within a defined time frame. Once the gavel falls, the winning bid becomes legally binding. Buyers typically pay a deposit on auction day and complete the purchase within a short period, often 28 days.

This clear process eliminates delays, avoids the stress of broken chains, and ensures fairness for both buyers and sellers. Unlike private sales, where negotiations can drag on for months, future auctions provide a secure and transparent path to property ownership.

Why Buyers Should Focus on Future Property Auctions

For buyers, future property auctions offer several advantages that make them an attractive choice:

  • Potential Bargains: Properties often sell below market value, presenting excellent opportunities for investors.
  • Wide Selection: Auctions feature residential homes, commercial properties, and land.
  • Fixed Timelines: Buyers know exactly when completion will take place.
  • Exclusive Properties: Some homes are only available through auctions.

At Property Buy Rent UK, we support buyers by analyzing upcoming catalogues, organizing property viewings, and reviewing legal packs. With expert guidance, buyers can approach future auctions with confidence and a clear strategy.

Why Sellers Benefit from Future Property Auctions

Sellers also stand to gain from future property auctions, as they deliver faster results and minimize risk. The benefits include:

  • Quick Sales: Most properties sell within weeks rather than months.
  • Competitive Prices: Multiple bidders can push final sale prices higher.
  • No Chain Delays: Auctions remove the problems associated with broken sales chains.
  • Secure Transactions: Once the gavel falls, the sale is legally binding.

By working with Property Buy Rent UK, sellers gain professional marketing, access to serious buyers, and effective auction coordination that ensures strong results in future auctions.

Preparing for Future Property Auctions

Success in future property auctions begins with preparation. Both buyers and sellers should take specific steps to improve their chances of achieving the best outcomes:

  1. Research Upcoming Catalogues: Identify suitable properties or auction dates early.
  2. Inspect Properties Thoroughly: Site visits provide a realistic picture of property condition.
  3. Review Legal Packs Carefully: These documents reveal ownership details, restrictions, and any risks.
  4. Secure Finances Early: Buyers must arrange deposits and funding before bidding.
  5. Develop a Strategy: A clear plan reduces stress and prevents costly mistakes.

At Property Buy Rent UK, we guide clients through each of these steps, ensuring they are fully prepared for future auctions.

Tips for Buyers at Future Property Auctions

To succeed at future property auctions, buyers should:

  • Set a Maximum Budget: Decide on a limit and avoid emotional overbidding.
  • Do Market Research: Compare similar properties to understand true value.
  • Get Expert Advice: Solicitors and financial advisors can highlight hidden risks.
  • Stay Calm on Auction Day: Confidence and discipline are essential in a fast-paced environment.

Following these tips helps buyers secure the right property at the right price.

Mistakes to Avoid

Even though future property auctions bring exciting opportunities, certain mistakes can prove costly. Common errors include:

  • Ignoring the legal pack and missing key details
  • Entering auctions without financing in place
  • Overbidding due to competition or pressure
  • Assuming every property is a bargain

At Property Buy Rent UK, we help clients avoid these pitfalls by providing expert advice, clear strategies, and tailored support.

Property Buy Rent UK: Your Auction Partner

Navigating future property auctions can feel overwhelming, especially for first-time buyers or sellers. That’s where Property Buy Rent UK makes a difference. We provide step-by-step support for buyers, including catalogue research, property inspections, and bidding strategies. For sellers, we deliver marketing expertise, auction planning, and direct access to motivated buyers.

Our mission is simple: to make future property auctions accessible, transparent, and profitable for everyone involved.

Conclusion

Future property auctions are set to play a major role in the UK property market. Buyers can benefit from unique opportunities, competitive prices, and fixed timelines, while sellers enjoy faster, more secure transactions.

At Property Buy Rent UK, we ensure clients are prepared for every stage of the auction process. Whether you are purchasing your first home, expanding your investment portfolio, or selling a property quickly, future property auctions create opportunities that traditional sales often cannot match.

Start preparing today with Property Buy Rent UK and unlock the advantages waiting in future property auctions.

Discussão (0)1
Entre ou crie uma conta para continuar
Pergunta
· Set. 26

The Role of Proper Planning in Successful Projects

No matter the size of a project whether it’s a home renovation, office build, or a large-scale development success always comes down to preparation. One of the most effective ways to avoid delays and budget issues is starting with an accurate building estimate.

A clear estimate gives everyone involved contractors, clients, and suppliers a realistic picture of costs and resources. It also reduces the risk of overspending or running short on materials halfway through.

In your experience, do you find software-based estimating more reliable, or do you still trust manual calculations?

Discussão (0)1
Entre ou crie uma conta para continuar