· Feb 25, 2016

Programmatically creating HL7v2 message, anyone?

A customer needs to assemble a HL7v2 ADR A19 (ADT Response - Patient Query) message programmatically, inside Ensemble.

Does anyone have an example of how can one create a HL7v2 message programmatically? 

So far, I could only find a brief note in WRC mailing, so I followed it. I have scubclassed EnsLib.HL7.MsgRouter.RoutingEngine class and implemented OnConstructReply() method but it seems to be NEVER called. I made sure this class is used as BP instead of original one, bound it to the routing rules, but no luck so far.

Can anyone advice?


Dan Kutac

Discussion (9)2
Log in or sign up to continue


there are lots of ways of doing this. I find thta building the segment data into strings is often the easiest way to do it because you can see what you have and mistakes are easier to avoid.

The example below builds strings with random data but you could be pulling it form a database. 

If you want to be more sophistcated you could use the SetValueAt() method of an HL7 Segment.

As Stefan says, looking at the generated code for a data transform can often give you good ideas.



//random values. These could be pulled from an application
set PID1=(1+$r(9))_$r(9999999)
set PID2=(1+$r(9))_$r(9999999)
set PID3=(1+$r(9))_$r(9999999)
set PID4=(1+$r(9))_$r(9999999)
set CID=(1+$r(9))_$r(9999999)
set PAC=(1+$r(9))_$r(9999999)

set firstname=##class(%PopulateUtils).FirstName()
set lastname=##class(%PopulateUtils).LastName()

set hl7=##class(EnsLib.HL7.Message).%New()
set hl7.DocType="2.5:ADT_A01"

set tSeg1=##class(EnsLib.HL7.Segment).ImportFromString("MSH|^~\&|HQ|A|||20070222140835||ADT^A01|1"_$r(99999999)_"R"_$R(99999999)_"|D|2.2||||||||||2.2b")

set tSeg2=##class(EnsLib.HL7.Segment).ImportFromString("EVN|A01|200702221400||ADM|MPACPB")
set tSeg3=##class(EnsLib.HL7.Segment).ImportFromString("PID|1|"_PID1_"|"_PID2_"^^^A^MR~"_PID3_"^^^B^PI~"_PID4_"^^^C^PI||"_lastname_"^"_firstname_"||20010101|U||W|122 BIRDSEED ROAD^^SKOKIE^IL^60077^US^^COOK|COOK|(847)676-2211||ENG|S|NON|3000018947054|111-11-1111|||||||||||N||||||||||||||||||||N")

set tSeg4=##class(EnsLib.HL7.Segment).ImportFromString("PD1|||||||O")
set tSeg5=##class(EnsLib.HL7.Segment).ImportFromString("PV1|1|I|E3E^3404^01^E|U|||000764^LERNER^DAVID JOSEPH^^MD^DR|||MED||||R|||000764^LERNER^DAVID JOSEPH^^MD^DR|I|7054|5^20070223|||||||||||||||||||E|||||200702221400|||||||A||000764^LERNER^^^MD^DR")
set tSeg6=##class(EnsLib.HL7.Segment).ImportFromString("PV2||P")
set tSeg7=##class(EnsLib.HL7.Segment).ImportFromString("DG1|1|FF|^OOO^FF||20050101|A|||||||||0||O")
set tSeg8=##class(EnsLib.HL7.Segment).ImportFromString("GT1|1|300001894^^^A^PI|BOOBOO^POOPOO||122 BIRDSEED ROAD^^SKOKIE^IL^60077^US^^COOK|(847)676-2211||20010101|U||P|111-11-1111||||001000^NONE|^^^^^US|||N")
set tSeg9=##class(EnsLib.HL7.Segment).ImportFromString("ZPI|1|N|||||||||20070220|N||^C|001000^NONE|^^^^^US")
set tSeg10=##class(EnsLib.HL7.Segment).ImportFromString("ZPV|1||||||||||N||||O||")
set tSeg11=##class(EnsLib.HL7.Segment).ImportFromString("ZP2|1|x|dgcode|")

set tsc=hl7.SetSegmentAt(tSeg1,1)

set tsc=hl7.InsertSegmentAt(tSeg2,2)
set tsc=hl7.InsertSegmentAt(tSeg3,3)

set tsc=hl7.InsertSegmentAt(tSeg4,4)
set tsc=hl7.InsertSegmentAt(tSeg5,5)
set tsc=hl7.InsertSegmentAt(tSeg6,6)
set tsc=hl7.InsertSegmentAt(tSeg7,7)
set tsc=hl7.InsertSegmentAt(tSeg8,8)
set tsc=hl7.InsertSegmentAt(tSeg9,9)
set tsc=hl7.InsertSegmentAt(tSeg10,10)
set tsc=hl7.InsertSegmentAt(tSeg11,11)

Thank you David,

but I have different problem. I admit my HL7v2 knowledge is limited. I have seen several scenarios where Ensemble acts as HL7 router, just accepting message at one end (service) and routing it to another end (operation) and eventually automatically sending ACK back to originator. 

But this case is different. Client is expecting immediate response - the ADR^A19 message. So I now have multiple ways of constructing response, but how do I actually return it back to the caller?



It looks as if  you are receiving a patient query (QRY_A19) so the approach depends on where the information for the reply is going to come from. 

If the BS has all that information in Ensemble then you can just do as you suggest. If it has to come from a downstream system then you might have to use business service setting 'AckMode=Application'. This means the business service will wait for an ACK  to be sent to it from downstream. If that response is exactly what you want, you can use it. Otherwise you will still have to override OnConstructReply to use the ACK to build exactly what you need.