async def handle_hl7_message(self, hl7_message): content = hl7_message.decode(self.encoding) msg = message.Message(content_type='text/hl7', payload=content, meta={}) try: result = await self.handle(msg) return result.payload.encode(self.encoding) except channels.Dropped: ack = hl7.parse(content, encoding=self.encoding) return str(ack.create_ack('AA')).encode(self.encoding) except channels.Rejected: ack = hl7.parse(content, encoding=self.encoding) return str(ack.create_ack('AR')).encode(self.encoding) except Exception: ack = hl7.parse(content, encoding=self.encoding) return str(ack.create_ack('AE')).encode(self.encoding)
def recv_handler(self, msg, server, connection): msg = msg.decode('utf-8') logger.debug('RECV: %s', msg.replace(CR, '\n')) # Logic here - parse the message HL7 # perform required validation # Send ack / error message that message received. # If enhanced mode, do the requisite steps to store then ack try: msg = hl7.parse(msg) except: logger.exception('Error parsing message') if self.postmortem: pdb.post_mortem() resp = responses.hl7NAK('AE', 'UNABLE TO PARSE REQUEST') logger.debug('SEND: %s', unicode(resp).replace(CR, '\n')) server._write_frame(connection, unicode(resp).encode('utf-8')) return try: # DISPATCH MESSAGE HERE. Expect an acknowledgement response message - resp = self.dispatcher.dispatch(msg) if resp is None: raise Exception('Application returned and invalid response (None) - response required') logger.debug('SEND: %s', unicode(resp).replace(CR, '\n')) server._write_frame(connection, unicode(resp).encode('utf-8')) return except: logger.exception('Error dispatching message') if self.postmortem: pdb.post_mortem() resp = responses.hl7NAK('AE', 'INTERNAL ERROR PROCESSING REQUEST') logger.debug('SEND: %s', unicode(resp).replace(CR, '\n')) server._write_frame(connection, unicode(resp).encode('utf-8')) return
def test_ack_message(self): container = HL7MessageContainer(PATIENT_UPDATE.replace("\n", "\r")) ohc_receiver = OhcReceiver() ack = ohc_receiver.handleMessage(container).result msh = MSH(hl7.parse(ack).segment("MSH")) self.assertEqual(msh.sending_application, "ELCID") self.assertEqual(msh.sending_facility, "UCLH")
def insertDocuments(Messages, feed, db, port): dbServer = 'localhost' dbPort = 27017 if len(db) > 0: dbServer = db if len(port) > 0: try: dbPort = int(port) except: print("Invalid db port provided") return "" client = MongoClient(dbServer, dbPort) dbName = feed + '_Analysis' db = client[dbName] message_collection = db['Message'] totalMessages = len(Messages) msgCount = 1 print("Total Messages: " + str(totalMessages)) for message in Messages: try: print("Processing Message " + str(msgCount) + " of " + str(totalMessages)) h = hl7.parse(message) doc = hl72MongoDocument(h) doc_id = message_collection.insert(doc) print("Inserted Message " + str(msgCount) + " with _id: " + doc_id) except: print("Error inserting document " + str(msgCount) + " Error: " + unicode(sys.exc_info()[0]) + "\n") msgCount += 1
def test_ack(self): msg = hl7.parse(sample_hl7) ack = msg.create_ack() self.assertEqual(msg["MSH.1"], ack["MSH.1"]) self.assertEqual(msg["MSH.2"], ack["MSH.2"]) self.assertEqual("ACK", ack["MSH.9.1.1"]) self.assertEqual(msg["MSH.9.1.2"], ack["MSH.9.1.2"]) self.assertNotEqual(msg["MSH.7"], ack["MSH.7"]) self.assertNotEqual(msg["MSH.10"], ack["MSH.10"]) self.assertEqual("AA", ack["MSA.1"]) self.assertEqual(msg["MSH.10"], ack["MSA.2"]) self.assertEqual(20, len(ack["MSH.10"])) self.assertEqual(msg["MSH.5"], ack["MSH.3"]) self.assertEqual(msg["MSH.6"], ack["MSH.4"]) self.assertEqual(msg["MSH.3"], ack["MSH.5"]) self.assertEqual(msg["MSH.4"], ack["MSH.6"]) ack2 = msg.create_ack(ack_code="AE", message_id="testid", application="python", facility="test") self.assertEqual("AE", ack2["MSA.1"]) self.assertEqual("testid", ack2["MSH.10"]) self.assertEqual("python", ack2["MSH.3"]) self.assertEqual("test", ack2["MSH.4"]) self.assertNotEqual(ack["MSH.10"], ack2["MSH.10"])
async def hl7sender(messageout): # Open the connection to the HL7 receiver. # Using wait_for is optional, but recommended so # a dead receiver won't block you for long try: hl7_reader, hl7_writer = await asyncio.wait_for( open_hl7_connection("127.0.0.1", 2100), #2100 for tester, 2575 default in PHP timeout=10) hl7_message = hl7.parse(messageout) # Write the HL7 message, and then wait for the writer # to drain to actually send the message hl7_writer.writemessage(hl7_message) await hl7_writer.drain() print(f'Sent message\n{hl7_message}'.replace('\r', '\n')) # Now wait for the ACK message from the receiever hl7_ack = await asyncio.wait_for(hl7_reader.readmessage(), timeout=10) ack = str(hl7_ack).replace('\r', '') print('{"STATUS":"SUCCESS","ACK":"' + ack + '"}') loop = asyncio.get_running_loop() loop.stop() except asyncio.CancelledError: # Cancelled errors are expected loop.stop() except Exception as e: print('{"STATUS":"' + str(e) + '"}') loop.stop()
def test_subcomponent(self): msg = hl7.parse(rep_sample_hl7) self.assertEqual( msg[1][3], [[["Component1"], ["Sub-Component1", "Sub-Component2"], ["Component3"]]], )
def test_nonstandard_separators(self): nonstd = 'MSH$%~\&$GHH LAB\rPID$$$555-44-4444$$EVERYWOMAN%EVE%E%%%L' msg = hl7.parse(nonstd) self.assertEqual(unicode(msg), nonstd) self.assertEqual(len(msg), 2) self.assertEqual(msg[1][5], ['EVERYWOMAN', 'EVE', 'E', '', '', 'L'])
def test_unicode(self): msg = hl7.parse(sample_hl7) self.assertEqual(unicode(msg), sample_hl7.strip()) self.assertEqual( unicode(msg[3][3]), '1554-5^GLUCOSE^POST 12H CFST:MCNC:PT:SER/PLAS:QN' )
def insertDocuments(Messages, feed, db, port): dbServer = 'localhost'; dbPort = 27017; if len(db) > 0: dbServer = db; if len(port) > 0: try: dbPort = int(port); except: print("Invalid db port provided"); return ""; client = MongoClient(dbServer, dbPort); dbName = feed + '_Analysis'; db = client[dbName]; message_collection = db['Message']; totalMessages = len(Messages); msgCount = 1; print("Total Messages: " + str(totalMessages)); for message in Messages: try: print("Processing Message " + str(msgCount) + " of " + str(totalMessages)); h = hl7.parse(message); doc = hl72MongoDocument(h); doc_id = message_collection.insert(doc); print("Inserted Message " + str(msgCount) + " with _id: " + doc_id); except: print("Error inserting document " + str(msgCount) + " Error: " + unicode(sys.exc_info()[0]) + "\n"); msgCount += 1;
def test_parsing_classes(self): msg = hl7.parse(sample_hl7) self.assertTrue(isinstance(msg, hl7.Message)) self.assertTrue(isinstance(msg[3], hl7.Segment)) self.assertTrue(isinstance(msg[3][0], hl7.Field)) self.assertTrue(isinstance(msg[3][0][0], unicode))
def test_parsing_classes(self): msg = hl7.parse(sample_hl7) self.assertIsInstance(msg, hl7.Message) self.assertIsInstance(msg[3], hl7.Segment) self.assertIsInstance(msg[3][0], hl7.Field) self.assertIsInstance(msg[3][0][0], str)
def test_nonstandard_separators(self): nonstd = 'MSH$%~\&$GHH LAB\rPID$$$555-44-4444$$EVERYWOMAN%EVE%E%%%L' msg = hl7.parse(nonstd) self.assertEqual(six.text_type(msg), nonstd) self.assertEqual(len(msg), 2) self.assertEqual(msg[1][5], [[['EVERYWOMAN'], ['EVE'], ['E'], [''], [''], ['L']]])
def test_extract(self): msg = hl7.parse(rep_sample_hl7) # Full correct path self.assertEqual(msg['PID.3.1.2.2'], 'Sub-Component2') self.assertEqual(msg[Accessor('PID', 1, 3, 1, 2, 2)], 'Sub-Component2') # Shorter Paths self.assertEqual(msg['PID.1.1'], 'Field1') self.assertEqual(msg[Accessor('PID', 1, 1, 1)], 'Field1') self.assertEqual(msg['PID.1'], 'Field1') self.assertEqual(msg['PID1.1'], 'Field1') self.assertEqual(msg['PID.3.1.2'], 'Sub-Component1') # Longer Paths self.assertEqual(msg['PID.1.1.1.1'], 'Field1') # Incorrect path self.assertRaisesRegexp(IndexError, 'PID.1.1.1.2', msg.extract_field, *Accessor.parse_key('PID.1.1.1.2')) # Optional field, not included in message self.assertEqual(msg['MSH.20'], '') # Optional sub-component, not included in message self.assertEqual(msg['PID.3.1.2.3'], '') self.assertEqual(msg['PID.3.1.3'], 'Component3') self.assertEqual(msg['PID.3.1.4'], '')
def test_ack(self): msg = hl7.parse(sample_hl7) ack = msg.create_ack() self.assertEqual(msg['MSH.1'], ack['MSH.1']) self.assertEqual(msg['MSH.2'], ack['MSH.2']) self.assertEqual('ACK', ack['MSH.9.1.1']) self.assertEqual(msg['MSH.9.1.2'], ack['MSH.9.1.2']) self.assertNotEqual(msg['MSH.7'], ack['MSH.7']) self.assertNotEqual(msg['MSH.10'], ack['MSH.10']) self.assertEqual('AA', ack['MSA.1']) self.assertEqual(msg['MSH.10'], ack['MSA.2']) self.assertEqual(20, len(ack['MSH.10'])) self.assertEqual(msg['MSH.5'], ack['MSH.3']) self.assertEqual(msg['MSH.6'], ack['MSH.4']) self.assertEqual(msg['MSH.3'], ack['MSH.5']) self.assertEqual(msg['MSH.4'], ack['MSH.6']) ack2 = msg.create_ack(ack_code='AE', message_id='testid', application="python", facility="test") self.assertEqual('AE', ack2['MSA.1']) self.assertEqual('testid', ack2['MSH.10']) self.assertEqual('python', ack2['MSH.3']) self.assertEqual('test', ack2['MSH.4']) self.assertNotEqual(ack['MSH.10'], ack2['MSH.10'])
async def test_readblock(self): message = r"MSH|^~\&|LABADT|DH|EPICADT|DH|201301011228||ACK^A01^ACK|HL7ACK00001|P|2.3\r" message += "MSA|AA|HL7MSG00001\r" self.reader.feed_data(START_BLOCK + message.encode() + END_BLOCK + CARRIAGE_RETURN) hl7_message = await self.reader.readmessage() self.assertEqual(str(hl7_message), str(hl7.parse(message)))
def test_extract(self): msg = hl7.parse(rep_sample_hl7) # Full correct path self.assertEqual(msg["PID.3.1.2.2"], "Sub-Component2") self.assertEqual(msg[Accessor("PID", 1, 3, 1, 2, 2)], "Sub-Component2") # Shorter Paths self.assertEqual(msg["PID.1.1"], "Field1") self.assertEqual(msg[Accessor("PID", 1, 1, 1)], "Field1") self.assertEqual(msg["PID.1"], "Field1") self.assertEqual(msg["PID1.1"], "Field1") self.assertEqual(msg["PID.3.1.2"], "Sub-Component1") # Longer Paths self.assertEqual(msg["PID.1.1.1.1"], "Field1") # Incorrect path self.assertRaisesRegex( IndexError, "PID.1.1.1.2", msg.extract_field, *Accessor.parse_key("PID.1.1.1.2") ) # Optional field, not included in message self.assertEqual(msg["MSH.20"], "") # Optional sub-component, not included in message self.assertEqual(msg["PID.3.1.2.3"], "") self.assertEqual(msg["PID.3.1.3"], "Component3") self.assertEqual(msg["PID.3.1.4"], "")
def test_parsing_classes(self): msg = hl7.parse(sample_hl7) self.assertIsInstance(msg, hl7.Message) self.assertIsInstance(msg[3], hl7.Segment) self.assertIsInstance(msg[3][0], hl7.Field) self.assertIsInstance(msg[3][0][0], six.text_type)
def test_writemessage(self): message = r"MSH|^~\&|LABADT|DH|EPICADT|DH|201301011228||ACK^A01^ACK|HL7ACK00001|P|2.3\r" message += "MSA|AA|HL7MSG00001\r" hl7_message = hl7.parse(message) self.writer.writemessage(hl7_message) self.transport.write.assert_called_with(START_BLOCK + message.encode() + END_BLOCK + CARRIAGE_RETURN)
def test_ack(self): msg = hl7.parse(sample_hl7, factory=TestFactory) ack = msg.create_ack() self.assertIsInstance(ack, TestMessage) self.assertIsInstance(ack(1)(9), TestField) self.assertIsInstance(ack(1)(9)(1), TestRepetition) self.assertIsInstance(ack(1)(9)(1)(2), TestComponent) self.assertEqual("R01", ack(1)(9)(1)(2)(1))
def test_nonstandard_separators(self): nonstd = "MSH$%~\\&$GHH LAB\rPID$$$555-44-4444$$EVERYWOMAN%EVE%E%%%L\r" msg = hl7.parse(nonstd) self.assertEqual(str(msg), nonstd) self.assertEqual(len(msg), 2) self.assertEqual(msg[1][5], [[["EVERYWOMAN"], ["EVE"], ["E"], [""], [""], ["L"]]])
def __stage_MSH_as_incoming_data(filename, source=None, logfile=None): """Consumes single-MSH single-PID HL7 files.""" _log.debug('staging [%s] as unmatched incoming HL7%s', gmTools.coalesce(source, u'', u' (%s)'), filename) # parse HL7 MSH_file = io.open(filename, mode = 'rt', encoding = 'utf8') raw_hl7 = MSH_file.read(1024 * 1024 * 5) # 5 MB max MSH_file.close() formatted_hl7 = format_hl7_message ( message = raw_hl7, skip_empty_fields = True, eol = u'\n' ) HL7 = pyhl7.parse(raw_hl7) del raw_hl7 # import file inc = create_incoming_data(u'HL7%s' % gmTools.coalesce(source, u'', u' (%s)'), filename) if inc is None: return None inc.update_data_from_file(fname = filename) inc['comment'] = formatted_hl7 if logfile is not None: log = io.open(logfile, mode = 'rt', encoding = 'utf8') inc['comment'] += u'\n' inc['comment'] += (u'-' * 80) inc['comment'] += u'\n\n' inc['comment'] += log.read() log.close() try: inc['lastnames'] = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__lastname) inc['firstnames'] = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__firstname) val = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__middlename) if val is not None: inc['firstnames'] += u' ' inc['firstnames'] += val val = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__dob) if val is not None: tmp = time.strptime(val, '%Y%m%d') inc['dob'] = pyDT.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tzinfo = gmDateTime.gmCurrentLocalTimezone) val = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__gender) if val is not None: inc['gender'] = val inc['external_data_id'] = filename #u'fk_patient_candidates', # u'request_id', # request ID as found in <data> # u'postcode', # u'other_info', # other identifying info in .data # u'requestor', # Requestor of data (e.g. who ordered test results) if available in source data. # u'fk_identity_disambiguated', # u'comment', # a free text comment on this row, eg. why is it here, error logs etc # u'fk_provider_disambiguated' # The provider the data is relevant to. except KeyError: _log.exception('no PID segment, cannot add more data') inc.save() return inc
def __stage_MSH_as_incoming_data(filename, source=None, logfile=None): """Consumes single-MSH single-PID HL7 files.""" _log.debug('staging [%s] as unmatched incoming HL7%s', gmTools.coalesce(source, '', ' (%s)'), filename) # parse HL7 MSH_file = io.open(filename, mode = 'rt', encoding = 'utf8', newline = '') raw_hl7 = MSH_file.read(1024 * 1024 * 5) # 5 MB max MSH_file.close() formatted_hl7 = format_hl7_message ( message = raw_hl7, skip_empty_fields = True, eol = '\n' ) HL7 = pyhl7.parse(raw_hl7) del raw_hl7 # import file incoming = gmIncomingData.create_incoming_data('HL7%s' % gmTools.coalesce(source, '', ' (%s)'), filename) if incoming is None: return None incoming.update_data_from_file(fname = filename) incoming['comment'] = formatted_hl7 if logfile is not None: log = io.open(logfile, mode = 'rt', encoding = 'utf8') incoming['comment'] += '\n' incoming['comment'] += ('-' * 80) incoming['comment'] += '\n\n' incoming['comment'] += log.read() log.close() try: incoming['lastnames'] = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__lastname) incoming['firstnames'] = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__firstname) val = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__middlename) if val is not None: incoming['firstnames'] += ' ' incoming['firstnames'] += val val = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__dob) if val is not None: tmp = time.strptime(val, '%Y%m%d') incoming['dob'] = pyDT.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tzinfo = gmDateTime.gmCurrentLocalTimezone) val = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__gender) if val is not None: incoming['gender'] = val incoming['external_data_id'] = filename #u'fk_patient_candidates', # u'request_id', # request ID as found in <data> # u'postcode', # u'other_info', # other identifying info in .data # u'requestor', # Requestor of data (e.g. who ordered test results) if available in source data. # u'fk_identity_disambiguated', # u'comment', # a free text comment on this row, eg. why is it here, error logs etc # u'fk_provider_disambiguated' # The provider the data is relevant to. except KeyError: _log.exception('no PID segment, cannot add more data') incoming.save() return incoming
def test_segments(self): msg = hl7.parse(sample_hl7) s = msg.segments('OBX') self.assertEqual(len(s), 2) self.assertIsInstance(s[0], Segment) self.assertEqual(s[0][0:3], [['OBX'], ['1'], ['SN']]) self.assertEqual(s[1][0:3], [['OBX'], ['2'], ['FN']]) self.assertIsInstance(s[0][1], Field)
def test_segments(self): msg = hl7.parse(sample_hl7) s = msg.segments("OBX") self.assertEqual(len(s), 2) self.assertIsInstance(s[0], Segment) self.assertEqual(s[0][0:3], [["OBX"], ["1"], ["SN"]]) self.assertEqual(s[1][0:3], [["OBX"], ["2"], ["FN"]]) self.assertIsInstance(s[0][1], Field)
def test_parse(self): msg = hl7.parse(sample_hl7, factory=TestFactory) self.assertIsInstance(msg, TestMessage) s = msg.segments("OBX") self.assertIsInstance(s[0], TestSegment) self.assertIsInstance(s[0](3), TestField) self.assertIsInstance(s[0](3)(1), TestRepetition) self.assertIsInstance(s[0](3)(1)(1), TestComponent) self.assertEqual("1554-5", s[0](3)(1)(1)(1))
def test_send_message_hl7_message(self): self.client.socket.recv.return_value = "thanks" message = hl7.parse(r"MSH|^~\&|GHH LAB|ELAB") result = self.client.send_message(message) self.assertEqual(result, "thanks") self.client.socket.send.assert_called_once_with( b"\x0bMSH|^~\\&|GHH LAB|ELAB\x1c\x0d")
def test_parse(self): msg = hl7.parse(sample_hl7) self.assertEqual(len(msg), 5) self.assertTrue(isinstance(msg[0][0][0], unicode)) self.assertEqual(msg[0][0][0], u'MSH') self.assertEqual(msg[3][0][0], u'OBX') self.assertEqual( msg[3][3], [u'1554-5', u'GLUCOSE', u'POST 12H CFST:MCNC:PT:SER/PLAS:QN'] )
def test_escape(self): msg = hl7.parse(rep_sample_hl7) self.assertEqual(msg.escape('\\'), '\\E\\') self.assertEqual(msg.escape('|'), '\\F\\') self.assertEqual(msg.escape('^'), '\\S\\') self.assertEqual(msg.escape('&'), '\\T\\') self.assertEqual(msg.escape('~'), '\\R\\') self.assertEqual(msg.escape('áéíóú'), '\\Xe1\\\\Xe9\\\\Xed\\\\Xf3\\\\Xfa\\')
def test_send_message_hl7_message(self): self.client.socket.recv.return_value = 'thanks' message = hl7.parse('MSH|^~\&|GHH LAB|ELAB') result = self.client.send_message(message) self.assertEqual(result, 'thanks') self.client.socket.send.assert_called_once_with( b'\x0bMSH|^~\&|GHH LAB|ELAB\x1c\x0d')
def test_repetition(self): msg = hl7.parse(rep_sample_hl7) self.assertEqual(msg[1][4], [["Repeat1"], ["Repeat2"]]) self.assertIsInstance(msg[1][4], Field) self.assertIsInstance(msg[1][4][0], Repetition) self.assertIsInstance(msg[1][4][1], Repetition) self.assertEqual(str(msg[1][4][0][0]), "Repeat1") self.assertIsInstance(msg[1][4][0][0], str) self.assertEqual(str(msg[1][4][1][0]), "Repeat2") self.assertIsInstance(msg[1][4][1][0], str)
def ACK(original_message, ack_code='AR'): """ Build a basic ACK message ``ack_code`` options are one of `AA` (accept), `AR` (reject), `AE` (error) (2.15.8) """ # hl7.parse requires the message is unicode already or can be easily converted via unicode() msg = hl7.parse(original_message) ack_response = create_msh_response(msg, ack_code) return unicode(ack_response)
def test_escape(self): msg = hl7.parse(rep_sample_hl7) self.assertEqual(msg.escape("\\"), "\\E\\") self.assertEqual(msg.escape("|"), "\\F\\") self.assertEqual(msg.escape("^"), "\\S\\") self.assertEqual(msg.escape("&"), "\\T\\") self.assertEqual(msg.escape("~"), "\\R\\") self.assertEqual(msg.escape("áéíóú"), "\\Xe1\\\\Xe9\\\\Xed\\\\Xf3\\\\Xfa\\")
def test_repetition(self): msg = hl7.parse(rep_sample_hl7) self.assertEqual(msg[1][4], [['Repeat1'], ['Repeat2']]) self.assertIsInstance(msg[1][4], Field) self.assertIsInstance(msg[1][4][0], Repetition) self.assertIsInstance(msg[1][4][1], Repetition) self.assertEqual(six.text_type(msg[1][4][0][0]), 'Repeat1') self.assertIsInstance(msg[1][4][0][0], six.text_type) self.assertEqual(six.text_type(msg[1][4][1][0]), 'Repeat2') self.assertIsInstance(msg[1][4][1][0], six.text_type)
def example2(): '''打印某些segment中的关键信息''' h = hl7.parse(msg) print h['PID'][0][5] ## Name print h['PID'][0][7] ## DOB print h['PID'][0][8] ## Gender print h['PID'][0][10] ## Country print h['PID'][0][19] ## Address print h['OBX'][0][3] ## Vital sign name print h['OBX'][0][5] ## Vital sign value
def test_send_message_hl7_message(self): self.client.socket.recv.return_value = 'thanks' message = hl7.parse('MSH|^~\&|GHH LAB|ELAB') result = self.client.send_message(message) self.assertEqual(result, 'thanks') self.client.socket.send.assert_called_once_with( b'\x0bMSH|^~\&|GHH LAB|ELAB\x1c\x0d' )
def test_assign(self): msg = hl7.parse(rep_sample_hl7) # Field msg['MSH.20'] = 'FIELD 20' self.assertEqual(msg['MSH.20'], 'FIELD 20') # Component msg['MSH.21.1.1'] = 'COMPONENT 21.1.1' self.assertEqual(msg['MSH.21.1.1'], 'COMPONENT 21.1.1') # Sub-Component msg['MSH.21.1.2.4'] = 'SUBCOMPONENT 21.1.2.4' self.assertEqual(msg['MSH.21.1.2.4'], 'SUBCOMPONENT 21.1.2.4') # Verify round-tripping (i.e. that separators are correct) msg2 = hl7.parse(six.text_type(msg)) self.assertEqual(msg2['MSH.20'], 'FIELD 20') self.assertEqual(msg2['MSH.21.1.1'], 'COMPONENT 21.1.1') self.assertEqual(msg2['MSH.21.1.2.4'], 'SUBCOMPONENT 21.1.2.4')
def test_file(self): # Extract message from file self.assertTrue(hl7.isfile(sample_file)) messages = hl7.split_file(sample_file) self.assertEqual(len(messages), 1) # message can be parsed msg = hl7.parse(messages[0]) # message has expected content self.assertEqual([s[0][0] for s in msg], ['MSH', 'EVN', 'PID', 'PD1', 'NK1', 'PV1'])
def test_append_from_source(self): # Copy a segment between messages MSH = hl7.Segment(SEP[0], [hl7.Field(SEP[1], ['MSH'])]) MSA = hl7.Segment(SEP[0], [hl7.Field(SEP[1], ['MSA'])]) response = hl7.Message(CR_SEP, [MSH, MSA]) response['MSH.F1.R1'] = SEP[0] response['MSH.F2.R1'] = SEP[1:] self.assertEqual(six.text_type(response), 'MSH|^~\\&|\rMSA') src_msg = hl7.parse(rep_sample_hl7) PID = src_msg['PID'][0] self.assertEqual(six.text_type(PID), 'PID|Field1|Component1^Component2|Component1^Sub-Component1&Sub-Component2^Component3|Repeat1~Repeat2') response.append(PID) self.assertEqual(six.text_type(response), 'MSH|^~\\&|\rMSA\rPID|Field1|Component1^Component2|Component1^Sub-Component1&Sub-Component2^Component3|Repeat1~Repeat2')
def test_elementnumbering(self): # Make sure that the numbering of repetitions. components and # sub-components is indexed from 1 when invoked as callable # (for compatibility with HL7 spec numbering) # and not 0-based (default for Python list) msg = hl7.parse(rep_sample_hl7) f = msg(2)(3)(1)(2)(2) self.assertIs(f, msg["PID.3.1.2.2"]) self.assertIs(f, msg[1][3][0][1][1]) f = msg(2)(4)(2)(1) self.assertIs(f, msg["PID.4.2.1"]) self.assertIs(f, msg[1][4][1][0]) # Repetition level accessed in list-form doesn't make much sense... self.assertIs(f, msg["PID.4.2"])
def create_alert(data): allalerts,alerts,reminders={},[],[] msg=hl7.parse(data) patient=get_patient(msg.segment('PID')[3][0]) if patient is None: patient=Patient(national_id=(msg.segment('PID')[3][0]),location=Location.objects.get(code=msg.segment('MSH')[5][0])) patient.save() try: reporter=get_reporter(None ,patient) except: reporter=Reporter.objects.filter(location=Location.objects.get(code=msg.segment('MSH')[5][0]),groups__pk=2)[0] report=create_report("SHR Alert", patient, reporter) report.save() fs=[x.key for x in FieldType.objects.filter(category__name="Risk")] for m in msg.segments('OBX'): description=m[3][1]#Description value=m[5][0]#Value if msg.segment('MSH')[20][0].lower()=="ALERT".lower() and value.lower() in fs: f=Field(type=FieldType.objects.get(key=value.lower())) f.save() report.fields.add(f) #if value.lower()=="chw": #remi=Reminder( reporter=reporter, report=report, type =ReminderType.objects.get(pk=6) ,date=datetime.datetime.now()) #remi.save() #reminders.append(remi) if "anc" in value.lower(): remi=Reminder( reporter=reporter, report=report, type =ReminderType.objects.get(pk=9) ,date=datetime.datetime.now()) remi.save() reminders.append(remi) if value.lower()=="edd": remi=Reminder( reporter=reporter, report=report, type =ReminderType.objects.get(pk=4) ,date=datetime.datetime.now()) remi.save() reminders.append(remi) for trigger in TriggeredText.get_triggers_for_report(report): alert=TriggeredAlert(reporter=report.reporter, report=report, trigger=trigger) alert.save() alerts.append(alert) #create alert here allalerts={'alerts':alerts,'reminders':reminders} return allalerts
def format_hl7_message(message=None, skip_empty_fields=True, eol='\n ', source=None): # a segment is a line starting with a type msg = pyhl7.parse(message) output = [] if source is not None: output.append([_('HL7 Source'), '%s' % source]) output.append([_('HL7 data size'), _('%s bytes') % len(message)]) output.append([_('HL7 Message'), _(' %s segments (lines)%s') % (len(msg), gmTools.bool2subst(skip_empty_fields, _(', skipping empty fields'), ''))]) max_len = 0 for seg_idx in range(len(msg)): seg = msg[seg_idx] seg_type = seg[0][0] output.append([_('Segment #%s <%s>') % (seg_idx, seg_type), _('%s fields') % len(seg)]) for field_idx in range(len(seg)): field = seg[field_idx] try: label = HL7_field_labels[seg_type][field_idx] except KeyError: label = _('HL7 %s field') % seg_type max_len = max(max_len, len(label)) if len(field) == 0: if not skip_empty_fields: output.append(['%2s - %s' % (field_idx, label), _('<EMTPY>')]) continue if (len(field) == 1) and (('%s' % field[0]).strip() == ''): if not skip_empty_fields: output.append(['%2s - %s' % (field_idx, label), _('<EMTPY>')]) continue content_lines = ('%s' % field).split(HL7_BRK) output.append(['%2s - %s' % (field_idx, label), content_lines[0]]) for line in content_lines[1:]: output.append(['', line]) #output.append([u'%2s - %s' % (field_idx, label), u'%s' % field]) if eol is None: return output max_len += 7 return eol.join([ '%s: %s' % ((o[0] + (' ' * max_len))[:max_len], o[1]) for o in output ])
def test_parse_hl7(): MSH_file = io.open(sys.argv[2], mode = 'rt', encoding = 'utf8', newline = '') raw_hl7 = MSH_file.read(1024 * 1024 * 5) # 5 MB max MSH_file.close() print(format_hl7_message ( message = raw_hl7, skip_empty_fields = True, eol = '\n' )) HL7 = pyhl7.parse(raw_hl7) del raw_hl7 for seg in HL7.segments('MSH'): print(seg) print("PID:") print(HL7.extract_field('PID')) print(HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__lastname)) print(HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__lastname))
def test_unescape(self): msg = hl7.parse(rep_sample_hl7) # Replace Separators self.assertEqual(msg.unescape('\\E\\'), '\\') self.assertEqual(msg.unescape('\\F\\'), '|') self.assertEqual(msg.unescape('\\S\\'), '^') self.assertEqual(msg.unescape('\\T\\'), '&') self.assertEqual(msg.unescape('\\R\\'), '~') # Replace Highlighting self.assertEqual(msg.unescape('\\H\\text\\N\\'), '_text_') # Application Overrides self.assertEqual(msg.unescape('\\H\\text\\N\\', {'H': '*', 'N': '*'}), '*text*') # Hex Codes self.assertEqual(msg.unescape('\\X20202020\\'), ' ')
def process_lab_message(message): '''Processes and HL7 lab message. Pulls out the necessary data for the clin.incoming_data_unmatched into a dictionary along with the raw message then passes it on to the interface to be put in the database. ''' h = hl7.parse(message) # temp = h.segment('PID')[2][0] formatter_message = {} formatter_message['external_id'] = handle_empty(string.rstrip(h.segment('PID')[2][0])) formatter_message['last_name'] = handle_empty(h.segment('PID')[5][0]) formatter_message['first_name'] = handle_empty(h.segment('PID')[5][1]) #See if the message has a middle name that will also go into the first name column in the table if len(h.segment('PID')[5]) < 2: formatter_message['first_name'] += " " + h.segment('PID')[5][2] #If Gender equals 'U' leave the value null #temp = h.segment('PID')[8][0] gender = string.rstrip(h.segment('PID')[8][0]) if (gender.upper() == 'M') or (gender.upper() == 'F'): formatter_message['gender'] = gender else: formatter_message['gender'] = None formatter_message['data_type'] = 'HL7' formatter_message['ordering_provider_information'] = handle_empty(" ".join(h.segment('OBR')[16])) formatter_message['data'] = message formatter_message['request_id'] = handle_empty(h.segment('ORC')[3][0]) #Build the other info information temp_list = [h.segment('PID')[2][0], h.segment('PID')[3][0], h.segment('PID')[4][0]] if len(h.segment('PID')) > 12: temp_list.append(h.segment('PID')[13][0]) temp_list = [w.strip() for w in temp_list if len(w) != 0] formatter_message['other_info'] = " ".join(temp_list) hl7_interface_to_gnumed.insert_unmatched_record(formatter_message)