Definition
Health Level 7 (HL7) is an international standard for the transmission of medical data and the name of the organization responsible for maintaining and growing this standard (among other things).
HL7 in OpenMRS
Available Message Parsers
- ORUR01Handler: Built into core
- Does not support the entire r01 specification
- See below for example messages
- Used by the FormEntry Module to process Infopath forms and xforms (HTML Form Entry is not using HL7)
- ADTA28: Built into core
- (Link to page describing what is implemented)
- (Link to other parsers developed by the community??)
Adding Custom Parsers
See Custom HL7 Handlers
Importing
Read about the HL7 Import Process.
Different options to get into that import process:
- Use the REST Module and its HL7 resource to post a message using curl or some other web service client.
- Posting an HL7 message to url /remotecommunication/postHl7.form will insert the message into the hl7 in queue.
- username: username to authenticate and save the message with
- password: password to authenticate and save the message with
- source: Name of an HL7Source in the system (A "LOCAL" hl7 source is shipped by default with openmrs)
- hl7Message: The hl7 message to save
- (Note: This was broken in 1.5.0, fixed against in 1.5.1 and 1.6+)
- Using the API, a message can be parsed with Context.getHL7Service().parseHL7String(String) --> processHL7Message(Message);
There might be a www.mirthcorp.com-community-overview Mirth module that uses the Web Services to create data in openmrs. In this case, hl7 messages would be posted to the mirth server, mirth would parse them and create the objects in openmrs via the web services.
Example Observation (ORU^R01) Message
Sample Message:
MSH|^~\&|FORMENTRY|AMRS|HL7LISTENER|AMRS|20050217152845||ORU^R01|AMRS20050217152845|P|2.5|1||||||||1^AMRS-ELDORET\^[http://schemas.openmrs.org/2006/FormEntry/formId]\^URI
PID||1^\^^AMRS|1MT^9^M10||Patient^Jonny^Dee{^}{^}DR|Patient^Momma^Thee^\^MS|20040101000000^Y|M||B|555 Johnson Road^Apt.555^Indianapolis^IN^46202^USA|||||||||||Indianapolis, IN|||||||||||||||||TRIBE CODE
PV1|1|O|^^^^^^^^^1^AMRS|2|||1^Mamlin^Joseph^^^^^^^^8^M10^^AMRS|||||||||||||||||||||||||||||||||||||20050217140000|||||||V
ORC|RE||||||||20050221130000|1^Enterer^Ima^^^^^AMRS
OBR|1|||1238^MEDICAL RECORD OBSERVATIONS^DCT
OBX|1|CE|1082^REVIEW OF SYSTEMS, CENTRAL NERVOUS SYSTEM^DCT||207^DEPRESSION^DCT||||||F|||20050217204000
OBX|2|SN|5497^CD4 COUNT^DCT||<^10|cells/mm3|10-1500|L|||F|||20050217204000
OBX|3|NM|5089^WEIGHT (KG)^DCT||25|kg|20-300|L|||F|||20050217204000
OBX|4|TS|1191^HISTORICAL DRUG STOP DATE^DCT||20050101||||||F|||20050217204000
Sample Acknowledgement:
MSH|^~\&|HL7LISTENER|AMRS|FORMENTRY|AMRS|20050217153200||ORU^R01^ACK|?|P|2.5
MSA|AR|AMRS20050217152845|
ERR||PID^1^3^^2|204|E
- MSH|
Message type (message header) and next character is the field separator
- FORMENTRY|
Sending Application
- HL7LISTENER|
Receiving Application
- 20050217152845|
Date/Time of Message (YYYYMMDDHHMMSS)
- ORU^R01|
Message Type (ORU = Unsolicited Transmisstion of an observation message
^ Event Type (R01 = Unsolicited Transmisstion of an observation message
- AMRS20050217152845|
Message Control ID (Unique identifier, RMRS uses sender + DT Stamp.. this is the "link" to the ACK, so we do need this)
- 2.5|
Version ID (HL7 version we're compliant with)
- 1|
Sequence Number (if we wanted to send a "batch" of these messages, we could append each encounter with a sequential number).. otherwise, always list 1.
- Continuation Pointer (not necessary)
- Accept Acknowledgement Type (not necessary)
- Application Acknowledgement Type (not necessary)
- Country Code (not necessary)
- Character Set (not necesary)
- Principal Language of Message (not necessary)
- Alternate Character Set Handling Schema (not necessary)
EVN (Event) Key (currently not implemented in OpenMRS):
EVN||20050221130000|||10^^^^^^^^^^9^M10^^AMRS
- EVN|
Message type (event)
- 20050221130000|
Recorded Date/Time
- 10^^^^^^^^^^9^M10^^AMRS|
Operator (10 = User ID (Erica))
^ Family Name
^ Given Name
^ Middle Name
^ Suffix
^ Prefix
^ Degree
^ Source Table
^ Assigning Authority
^ Name Type Code
^ Identifier Check Digit (9)
^ Check Digit Scheme (M10)
^ Identifier Type Code
^ Assigning Facility (AMRS)
PID (Patient Identification) Key:
PID|||1MT^0^M10||Patient^Jonny^Dee^DR|Patient^Momma^Thee^MS|20040101000000|M||B|555 Johnson Road^Apt. 555^Indianapolis^IN^46202^USA|||||||||||Indianapolis, IN|||||||||||||||||TRIBE CODE
- PID|
Message type (patient identification)
- Set-ID (not necessary in our system.. we could represent multiple PIDs from different systems with multiple PID segments, one from each system with this)
- Patient ID (older version of identifier representation.. no longer used commonly)
- 1MT^0^M10|
ID Number (1MT)
^ Check Digit (0)
^ Check Digit Scheme (M10)
^ Assigning Authority (hopefully won't have to use.. but if we need multiples)
// a ~ would separate multiple occurrences of PIDs
- Alternate Patient ID (older version of identifier representation.. no longer used commonly)
- Patient^Jonny^Dee^^DR|
Family Name (Patient)
^ Given Name (Jonny)
^ Second / Middle Name (Dee)
^ Suffix ()
^ Prefix (DR)
- Patient^Momma^Thee^^MS|
Mother's Maiden Family Name (Patient)
^ Given Name (Momma)
^ Second / Middle Name (Thee)
^ Suffix ()
^ Prefix (MS)
- 20040101000000|
Date/Time of Birth (YYYYMMDDHHMMSS)
^ Degree of Precision (for our purposes Y = estimated, and null = actual)
- M|
Administrative Sex (M) .. M, F, O, U, A, N possible answers
- Patient Alias (older version.. no longer used commonly)
- B|
Race (B) .. I, A, B, W, N, O possible answers
- 555 Johnson Road^Apt. 555^Indianapolis^IN^46202^USA|
Street Address
^ Other Designation
^ City
^ State
^ Zip
- Country Code (older version.. no longer used commonly)
- SSN - Patient (older.. use PID-3 for this, store here for BW compat)
- Driver's License Number - Patient (older.. use PID-3 for this, store here for BW compat)
- Indianapolis, IN|
Birth Place
- Patient Death Date and Time
- Identity Unknown Indicator
- Identity Reliability Code
- Tribal Citizenship (here is where we can list the tribe.. it's loosely defined in HL7.. we could just send the code from our list with this)
PV1 (Patient Visit) Key:
PV1|1|O|^^^^^MTRH^1^AMRS|2|||1^Mamlin^Joseph^^^^^^^8^M10^^AMRS|||||||||||||||||||||||||||||||||||||20050217140000|||||||V
This message creates an encounter in OpenMRS.
- PV1|
Message type (patient visit)
- O|
Patient Class (O = Outpatient)
- ^^^^^^^^MTRH^1^AMRS|
Assigned Patient Location (1=MTRH)
- 2|
Admission Type (2 = Return)
- 1^Mamlin^Joseph^^^^^^^^8^M10^^AMRS|
Attending Doctor ID (1)
^ Family Name (Mamlin)
^ Given Name (Joseph)
^ Middle Name
^ Suffix
^ Prefix
^ Degree
^ Source Table
^ Assigning Authority
^ Name Type Code
^ Identifier Check Digit (8)
^ Check Digit Scheme (M10)
^ Identifier Type Code
^ Assigning Facility (AMRS)
- Transfer to Bad Debt Code
- Transfer to Bad Debt Date
- 20050217140000|
Admit Date/Time
V Visit indicator (V = visit level, A = account level) |
ORC (Common Order Segment):
ORC|RE||||||||20050221130000|1^Enterer^Ima^^^^^AMRS
NOTE: The optional ORC segment is used to transmit enterer and date-entered information in the message.
- ORC|
Message type (common order request)
- RE|
Order Control (RE = observations to follow)
- 20050221130000|
Date/Time of Transaction
- 1^Enterer^Ima^^^^^^^^^^^AMRS
Entered By ID (1)
^ Family Name (Enterer)
^ Given Name (Ima)
^ Middle Name
^ Suffix
^ Prefix
^ Degree
^ Source Table
^ Assigning Authority
^ Name Type Code
^ Identifier Check Digit
^ Check Digit Scheme
^ Identifier Type Code
^ Assigning Facility (AMRS)
OBR (Observation Request) Key:
OBR|1|||1238^MEDICAL RECORD OBSERVATIONS^DCT|
- OBR|
Message type (observation request)
- 1|
Set ID (1) .. sequential number given to each subsequent OBR.
- 1238^MEDICAL RECORD OBSERVATIONS^DCT|
Identifier (1238)
^ Text (MEDICAL RECORD OBSERVATIONS)
^ Name of Coding System (DCT)
- Observation Date/Time (We could list this for posterity's sake, but it's unneeded if you think about it.. as each OBX has it's datetime. RG doesn't typically fill this.
OBX / CE (Observation Result, Coded Datatype) Key:
OBX||CE|1082^REVIEW OF SYSTEMS, CENTRAL NERVOUS SYSTEM^DCT||207^DEPRESSION^DCT||||||F|||20050217204000
- 1|
Set ID .. sequential number given to each subsequent OBX within the series.
- 1082^REVIEW OF SYSTEMS, CENTRAL NERVOUS SYSTEM^DCT|
Concept ID (1082)
^ Text Description (REVIEW OF SYSTEMS)
^ Name of Coding System (DCT)
- 207^DEPRESSION^DCT|
Concept ID (207)
^ Text Description (DEPRESSION)
^ Name of Coding System (DCT)
- Observation Result Status
- User Defined Access Checks
- 20050217204000|
Date/Time of Observation
OBX / SN (Observation Result, Structured Numeric Datatype) Key:
OBX|2|SN|5497^CD4 COUNT^DCT||<^10|cells/mm3|10-1500|L|||F|||20050217204000
- 2|
Set ID ... sequential number given to each subsequent OBX within the series.
- 5497^CD4 COUNT^DCT|
Concept ID (5497)
^ Text Description (CD4 COUNT)
^ Name of Coding System (DCT)
- <^10|
Comparator (<)
^ Value 1 (10)
- 10-1500|
References Range
- L|
Abnormal Flags (we can decide if we want to use this one)
- Observation Result Status
- User Defined Access Checks
- 20050217204000|
Date/Time of Observation
OBX / NM (Observation Result, Numeric Datatype) Key:
OBX|3|NM|5089^WEIGHT (KG)^DCT||25|kg|20-300|L|||F|||20050217204000
- 3|
Set ID ... sequential number given to each subsequent OBX within the series.
- 5089^WEIGHT (KG)^DCT|
Concept ID (5089)
^ Text Description (WEIGHT (KG))
^ Name of Coding System (DCT)
- L|
Abnormal Flags (we can decide if we want to use this one)
- Observation Result Status
- User Defined Access Checks
- 20050217204000|
Date/Time of Observation
OBX / NM (Observation Result, Timestamp Datatype) Key:
OBX|4|TS|1191^HISTORICAL DRUG STOP DATE^DCT||20050101||||||F|||20050217204000
- 4|
Set ID ... sequential number given to each subsequent OBX within the series.
- 1191^HISTORICAL DRUG STOP DATE^DCT|
Concept ID (1191)
^ Text Description (HISTORICAL DRUG STOP DATE)
^ Name of Coding System (DCT)
- 20050101|
DateTime could be of the form (YYYYMMDD) or (YYYYMMDDHHMMSS)
- L|
Abnormal Flags (we can decide if we want to use this one)
- Observation Result Status
- User Defined Access Checks
- 20050217204000|
Date/Time of Observation
MSA (Message Acknowledgement) Key:
MSA|AR|AMRS20050217152845|
- MSA|
Message Header (Acknowledgement Segment)
- AR|
Acknowledgement Code (AR)
HL7 Table 0008 has the list of possible values, but in our case, we only care about 3 (I think):
- AA = Application Accept
- AE = Application Error
- AR = Application Reject
In this case, the message notes that this message was rejected, b/c the MRN had an invalid check digit.
- AMRS20050217152845|
Message Control ID (this comes from the MSH segment Control-ID and provides the linkage)
ERR (Error Segment) Key:
This segment is used to add specific error comments to acknowledgement messages:
- ERR|
Message type (error segment)
- Error Code and Location (no longer commonly used/deprecated)
- PID^1^3^^2|
Error Location Segment ID (PID)
^ Segment Sequence (1)
^ Field Position (3)
^ Field Repetition
^ Component Number (2)
^ Subcomponent Number
(in this example.. patient has an incorrect check digit.. it should be '0'
)
- 204|
HL7 Error Code (204)
HL7 Table 0357 lists the possible codes, 204 is "unknown key identifier"
W = Warning, I = Information, E = Error
Example of Grouped Observations
Here's an example of what where we're headed for grouped observations (see COMPLETE BLOOD COUNT below). To be valid HL7, the enterer and datetime for data entry either need to move from the ORC to OBR segments or the ORC needs to be repeated for each OBR. --Burke 12:24, 9 August 2006 (EDT)
MSH|^~\&|FORMENTRY|AMRS|HL7LISTENER|AMRS|20060809121931||ORU^R01|formentry-20060809121931|P|2.5|1||||||||2^AMRS-ELDORET^http://schema.openmrs.org/2006/FormEntry/formId^URI
PID|||1^^^AMRS-ELDORET&openmrs.org&DNS^||Patient^John^D||
PV1||O|1^Unknown||||2^Ima Doc (2-6)|||||||||||||||||||||||||||||||||||||20060807|||||||V
ORC|RE||||||||20060807161605|1^Super User
OBR|1|||1238^MEDICAL RECORD OBSERVATIONS^99DCT
OBX|1|NM|5089^WEIGHT (KG)^99DCT||70|||||||||20060807
OBR|2|||1019^COMPLETE BLOOD COUNT^99DCT
OBX|1|NM|1015^HEMATOCRIT^99DCT||1000|||||||||20060807
OBX|2|NM|21^HEMOGLOBIN^99DCT||1000|||||||||20060807
OBX|3|NM|678^WHITE BLOOD CELLS^99DCT||100000|||||||||20060807
OBX|4|NM|729^PLATELETS^99DCT||10|||||||||20060807
OBR|3|||1284^PROBLEM LIST^99DCT
OBX|1|CWE|6042^PROBLEM ADDED^99DCT||2^ANEMIA, HEMOLYSIS^99DCT|||||||||20060807
Other Examples
To successfully process a ADT_A28 message is required specified within the PID-3 segment the (HD)> <assigning Authority>, in this case "Old Identification Number"
MSH|^~\&|sistemaExterno||EXTERNAL|EXTHL7|20091123101300^0|HUP|ADT^A28^ADT_A05|9166768|P|2.5|1|||AL||ASCII
EVN|A28|20091123101300|||1
PID|||4^^^Old Identification Number||FARMACIA^UNO^PACIENTE||20011114|M|||20371^02^2400^724||||||724^Y||||||02|||11|20371|724^ESPA?A^N||N
PV1|1|I
PV2||||||||||||||||||||||||||||||||||||N
GT1|1||||||||||^^^T
MSH|^~\&|FORMENTRY|AMRS|HL7LISTENER|AMRS|20060809121931||ORU^R01|formentry-20060809121931|P|2.5|1||||||||2^AMRS-ELDORET^http://schema.openmrs.org/2006/FormEntry/formId^URI
PID|||3^^^^||Patient^John^D||
PV1||O|1^Unknown||||2^Ima Doc (2-6)|||||||||||||||||||||||||||||||||||||20060807|||||||V
ORC|RE||||||||20060807161605|1^Super User
OBR|1|||1238^MEDICAL RECORD OBSERVATIONS^99DCT
OBX|1|NM|5089^WEIGHT (KG)^99DCT||70|||||||||20060807
OBR|2|||1019^COMPLETE BLOOD COUNT^99DCT
OBX|1|NM|1015^HEMATOCRIT^99DCT||1000|||||||||20060807
OBX|2|NM|21^HEMOGLOBIN^99DCT||1000|||||||||20060807
OBX|3|NM|678^WHITE BLOOD CELLS^99DCT||100000|||||||||20060807
OBX|4|NM|729^PLATELETS^99DCT||10|||||||||20060807
OBR|3|||1284^PROBLEM LIST^99DCT
OBX|1|CWE|6042^PROBLEM ADDED^99DCT||2^ANEMIA, HEMOLYSIS^99DCT|||||||||20060807
Resources
1 Comment
user-b907a
Edit: I was asked to change it in the wiki so the ADT28 message reflects now my solution below.
Some issue I encountered during the patient creation using the ADT28 message above (after adjusting the header to my installation, dropping the PV, GT sections) was that the patient creation silently failed. I solved this problem by adding a third ^ to the corresponding segment in the PID block.
Perhaps the given ADT28 message indicates the "Old Identification Number" as a validation scheme instead of the assigning authority.
My final ADT28 message that creates a patient looks as follows (red text shows the fields that I changed for my setting):
MSH|^~\&|FORMENTRY|ChariteSAP|HL7LISTENER|LOCAL|20091123101300^0|HUP|ADT^A28^ADT_A05|9166768|P|2.5|1|||AL||ASCII
EVN|A28|20091123101300|||1
PID|||1338^^^Old Identification Number||Patient^Demo^OldId||20011114|M|||20371^02^2400^724||||||724^Y||||||02|||11|20371|724^DEUT^N||N