by Rahul Bhagat
What happens if these characters are part of the data? Let’s consider an example.
Ben & Jerry’s Diagnostic Center sends the result of a test as an HL7 message to the ordering hospital. The hospital system receives the message and starts reading it to parse the data (pull out field values) and save it to a database. When the system gets to the Sending Facility field (MSH-4), it will read “Ben” and then run into the & symbol. At that point, the system is being told that the name of the facility has a sub-component. Facility names don’t have sub-components (if you check the segment attribute table), so in all likelihood the system doesn’t have a corresponding field in the database to save the value “Jerry’s Diagnostic Center”.
This is a recipe for application failure. Let’s assume this is a futuristic, can-handle-anything kind of system, but even then the system is only saving “Ben” as the name of the sending facility, which is incorrect. The doctor reading the lab report will see that “Ben” sent the test result. I don’t know how much faith she will have in the report.
So what do we do? We can’t ask Ben & Jerry’s Diagnostic Center to change its name.
This is where the escape character comes to the rescue. If characters, which have special meaning in HL7, need to be transmitted as part of the data, then all one needs to do is replace the character with its corresponding escape sequence. The system reading it will read the escape sequence and replace it with that special character before saving it.
An escape sequence is nothing more than one or more characters surrounded by the escape character (). Every special character in HL7 has a corresponding escape sequence. There are many escape sequences for formatting and highlighting text, and you can even create custom escape sequences.
Here are the escape sequences for the symbols we have already discussed:
Guess how Ben & Jerry’s Diagnostic Center will be encoded in an HL7 message. You will replace the encoding character & with its corresponding escape sequence so that you will have “Ben T Jerry’s Diagnostic Center” encoded in the message. The receiving system will recognize T as an escape sequence and replace it with the & symbol when the data is saved locally.
MSH-3: Sending Application & MSH-4: Sending Facility
Fields three and four are optional, but they are almost always populated in real world implementations. They contain the name of the application and the facility that sent the message (the sending system). Often these fields are used as filter to process or route messages based on the sending application and facility.
For an example, if Ben & Jerry’s Diagnostic Center is running a Meditech system, then the sending application will be “Meditech” in MSH-3 and the sending facility, “Ben & Jerry’s Diagnostic Center” (or an abbreviation B&J DIAG) will be in the MSH-4 field.
MSH-5: Receiving Application & MSH-6: Receiving Facility
Fields five and six are similar to fields three and four except that they contain the name of the application and the facility that the message is being sent to (the receiver). These fields too are used in real world implementations as a filter to route or process messages based on the intended recipient.
MSH-7: Date/Time of Message
This is a required field. It captures the date and time when the sending system created the message. In a North American context, the field is usually populated in the format YYYYMMDDHHMM (where Y = year, M = month and so on). Some sites go to a higher degree of precision and include seconds or even milliseconds in the field. HL7 allows up to 26 characters, so we have a lot of room here!
MSH-9: Message Type
Message Type is a very important field and a valid value in this field is required for every message. This is the field that tells the receiving system the type of message it is. Knowing the type of message is essential for a system to be able to read the message.
Without this information, the receiving system will be like the early archeologists in Egypt. They had no idea what the birds and the eyes in hieroglyphs meant. It wasn’t until the Rosetta stone was discovered by Napoleon’s troops and Champollion figured out a way to read it, that hieroglyphs started to make sense. This is what message type does to the receiving system.
The message type field has three components – Message Type (MSH-9.1), Trigger Event (MSH-9.2) and Message Structure ID (MSH-9.3). In our example, this field has the value ADT^A04. Notice something? Only the first two components are there. This is fine because the third component is an optional component and usually we leave it empty. If you want to know the Message Structure ID of a message, you can look it up in HL7 specs where the abstract message structure is defined. It’s in the heading.
We have already discussed message types (MSH-9.1) and trigger events (MSH-9.2). If you need to refresh, they are in Chapter 5.
MSH-10: Message Control ID
The purpose of this field is to uniquely identify each and every message. Usually, the value in this field is a unique number generated by the sending system. For each subsequent message, the sending system increments this number by one to generate another unique number. Some systems also attach a date stamp at the end of the number to eliminate any chances of duplication.
Why do we need to uniquely identify each message?
When the receiving system gets the message, it has to send an acknowledgement back to the sending system. Acknowledgement tells the sending system if the message was received ok and if it can move on or whether there are defects in the message and it needs to resend it. The receiving system uses the Message Control ID to tell the sending system which message it is talking about. And that is why we need to uniquely identify each and every message.
Troubleshooting is another reason why we need a unique ID for every message. At the time of debugging and testing, MSH-10 is an invaluable piece of information. It helps track down an individual message in a haystack of messages.
MSH-11: Processing ID
This is a required field, which contains a single character. It signals whether the message is real (production in techie speak) or just for testing. If the value is P, it signals that it is a production or real message. If the value is T (Test/ Training) or D (Development) then it is a test message.
MSH-12: Version ID
This is another required field that is of interest only to developers and interface analysts. This field contains the version number of HL7 that the message conforms to. In our example this value is 2.5, which means the message conforms to HL7 version 2.5.
MSH-15: Accept Acknowledgement Type & MSH-16: Application Acknowledgement Type
Remember the discussion on message acknowledgement in chapter 5? Even if you do, here’s a quick recap.
There are two types of acknowledgement messages – original & enhanced. In the original mode only one acknowledgement message is sent. It is sent by the receiving application, hence its name, application acknowledgement.
In the enhanced mode, two acknowledgement messages are sent. One is the application acknowledgement and the other one is accept acknowledgement. Accept acknowledgement is sent when the receiving system has successfully saved the message at its end.
In other words, in enhanced mode, when the receiving system accepts the delivered message, it sends out an accept acknowledgement. It then sends the message to the application, which does its own verification and sends out an application acknowledgement.
Fields MSH-15 and MSH-16 act like switches for these two acknowledgement types. If the value is AL in MSH-15 then the receiving system is supposed to “ALways” send an accept acknowledgement. If the value is NE then it should “NEver” send an accept acknowledgement. The same codes are used in the MSH-16 field, only this time it pertains to the application acknowledgement message.
For most practical purposes, these fields are useless. This is because we don’t use enhanced mode of acknowledgement much. Usually people just leave these fields empty, which means original mode. If you want to use the enhanced mode, then you will have to have AL in both the
fields. If you just want to know that the message was received successfully, then you will have AL in MSH-15 as in our example message.
Event Type Segment (EVN)
Event Type is a required control segment in many message types, such as patient administration (ADT) and financial management (BAR). It is a short segment with seven fields, only one of which is required. It has “good to know” kind of information but nothing critical. But the segment is so common in HL7 messages that I felt you should know about it.
The only useful information this segment has, in my opinion, is the time when the event happened, EVN-2.
Here is the EVN segment from the example message.
EVN|A04|201310201500|||ID221^Dude@Terminal
EVN-1: A04 (Event Type Code)
EVN-2: 201310201500 (Recorded Date/Time)
EVN-3:
EVN-4:
EVN-5: ID221^Dude@Terminal (Operator ID)
EVN-6:
EVN-7:
This example is very typical of EVN segments in the real world. You have the trigger event code (A04) in the first field even though it is not required and is a repeat from MSH-9.2. And then there is the Recorded Date/Time, the only required field in this segment. Among the optional fields, EVN-1 and EVN-5 are generally populated.
EVN-1: Event Type Code
As the name suggests, this field holds the trigger event code. It is a duplicate of MSH-9.2 and retained for use by systems using older versions of HL7.
You will always find this field populated. This is because EVN-1 used to hold the trigger event code before a newer version of HL7 came along and moved the trigger event code to MSH-9.2. People kept populating the value in EVN-1 to maintain compatibility with older versions. Who wanted to come back and recode the interfaces! A little duplication didn’t sound like a big price to pay and now it’s baked in.
EVN-2: Recorded Date/Time
This is the only required field in this segment. It holds the date and time (YYYYMMDDHHMMSS) of the trigger event. To use our example message, the value in EVN-2 is the moment when, after filling out the form, the person at the desk hits the submit button to register the patient.
EVN-5: Operator ID
This is an optional field that holds the identifying information of the person at the desk. It identifies the “dude” at the terminal. He is the one who hit the submit button to register the patient. The field contains his employee ID and name.
Now you know where to look if you want to find out who did the registration.
Notes & Comments Segment (NTE)
NTE is a general purpose segment. As the name suggests, this is a segment for notes and comments. You will find this segment peppered all over the place in order and report messages.
If you look at the abstract message structure of a general order (ORM^O01) or a result (ORU^R01) message, you will find NTE at multiple places. And it is always enclosed between square and curly brackets; it’s always optional and repeatable.
The reason this segment is in multiple places is because an NTE is always associated with the segment it came after. If an NTE is after a PID segment, it holds notes & comments about the patient. If it is after OBX segment (result) then it holds notes & comments about the result.
The segment itself is very short. It only has four fields, which are all optional.
NTE-1: Set ID - NTE
This field assigns a number to an NTE segment. NTE commonly repeats to accommodate long comments and this field helps to identify individual segments in that comment.
Numbering starts at 1 and increases by increments of one until that comment is done. The next time another NTE is used, the numbering starts again from 1. So if there is a comment about the patient, it will have a bunch of NTEs numbered 1 to n. If there is another group of NTEs for result, they too will be numbered 1 to n.
I have come across messages with beautifully formatted comments and dotted borders. They really grab your attention in a sea of random characters. Who says techies aren’t artistic!
Let’s consider an example. Suppose the following comments were to be included in an order message for a blood test:
Patient comment (after PID)
The patient was very particular about his breakfast. He consumed an orange before the blood was drawn.
Order comment (after OBR)
If the test results will be affected because of consumption of a citrus fruit, please give us a call. We will cancel this order and create another one.
A creative sender with a flair for design could send the comments something like this:
PID|…….
NTE|1||----------------------------------------------------------------|
NTE|2|| The patient was very particular about his breakfast|
NTE|3|| He consumed an orange before the blood was drawn|
NTE|4||----------------------------------------------------------------|
.
.
OBR|…..
NTE|1||----------------------------------------------------------------|
NTE|2| If the test results will be affected because of |
NTE|3|consumption of a citrus fruit, please give us a call|
NTE|4||We will cancel this order and create another one|
NTE|5||----------------------------------------------------------------|
Notice how the NTE segments are numbered 1,2,3,4… for each comment. That is the Set ID to identify individual NTE’s in a group.
NTE-3: Comment
This is the field that holds the actual notes & comments in free-form text. You can even format the text (highlight etc.) by including appropriate escape sequences.
Acknowledgement Control Segments
A general acknowledgement message is made entirely of control segments. Of course, MSH is the first segment in the message. It is always the first segment, no matter what the message type. After that you have MSA, the acknowledgement segment and if there are errors, you will have ERR segments. That’s it. These are the only segments in an acknowledgement message.
HL7 does allow customized acknowledgement messages but in real life, we only use the general acknowledgement message with its simple message structure.
For a successful message, a positive acknowledgement (ACK in short form) is sent, which is even simpler and has only two types of segments - MSH & MSA. For example,
MSH|^~&|RECEIVER_APP|RCVD_BY|SENDER_APP|SENT_BY|201310201501||ADT^A04| R_MSG_ID279|P|2.5|||AL
MSA|AA|MSG_ID001|Got your message
For an unsuccessful message, a negative acknowledgement (NAK in short form) is sent, which can have three types of segments (MSH, MSA & ERR). The ERR segment can repeat if there is more than one error to report.
In the example below we have two errors to report, hence two ERR segments.
MSH|^~&|RECEIVER_APP|RCVD_BY|SENDER_APP|SENT_BY|201310201501||ADT^A04| R_MSG_ID279|P|2.5|||AL
MSA|AE|MSG_ID001|Can’t read this message.
ERR||PID^5|101^Required field missing|E
ERR||PID^7|102^Data type error|E
Now, let’s look more closely at these control segments (MSA & ERR) in an acknowledgement message.
Message Acknowledgement Segment (MSA)
MSA is a required segment in every acknowledgement message. This is the segment that holds the acknowledgement code, which tells you if the receiver was able to process the message or not.
The segment has six fields, out of which only the first two are required. In practice, the third field, which is optional, is also populated. The last three are always empty.
MSA-1: Acknowledgement Code
When people look at acknowledgement messages, this is the first field their eyes go to. The first field of the MSA segment holds the all-important acknowledgement code.
The acknowledgement code is made up of two uppercase letters. If the value is AA that means all is good. For error messages, we have two codes – AE and AR.
AE means there is a problem with the message. It
could be its content, structure or something else but most probably the source of the problem is the sender. If it is AR, then that means there is some other system level problem, such as disk space issues or a power failure. In this case, the source of the problem could be the receiver and most probably you will need to resend the message.
MSA-2: Message Control ID
This is the second required field in the MSA segment. It contains the Message Control ID (MSH-10) of the original message. If you remember, the message control ID uniquely identifies a message and by including it here, the acknowledgement message is indicating that this acknowledgement is for the message with control ID in MSA-2.
Let’s clarify this with the help of an example below. The original message has its control ID in MSH-10 (MSG_ID001) and the same control ID is in MSA-2 of the acknowledgement message. Keep in mind though, that the acknowledgement message also has its message control ID in MSH-10 (R_MSG_ID279), which is different from the message control ID of the original message.
(Original Message)
MSH|^~&|SENDER_APP|SENT_BY|RECEIVER_APP|RCVD_BY|201310201500||ADT^A04| MSG_ID001|P|2.5|||AL
(Acknowledgement Message)
MSH|^~&|RECEIVER_APP|RCVD_BY|SENDER_APP|SENT_BY|201310201501||ADT^A04| R_MSG_ID279|P|2.5|||AL
MSA|AA| MSG_ID001|Got your message
Without this ID, there is no way for the sending system to know which message the receiver is acknowledging.
MSA-3: Text Message
This is an optional field that can be used to send additional information like error details. Newer versions of HL7 don’t recommend using this field. We have a brand new segment (ERR) to provide detailed information about errors.