def test_message_profile(self): m = parse_message(self.rsp_k21, message_profile=self.rsp_k21_mp, validation_level=VALIDATION_LEVEL.TOLERANT) self.assertEqual(m.qpd.qpd_3.datatype, 'QIP') self.assertFalse(m.qpd.allow_infinite_children) m = parse_message(self.rsp_k21, message_profile=self.rsp_k21_mp, validation_level=VALIDATION_LEVEL.STRICT) self.assertEqual(m.qpd.qpd_3.datatype, 'QIP') self.assertFalse(m.qpd.allow_infinite_children)
def server_program(): # get the hostname host = socket.gethostname() port = 5000 # initiate port no above 1024 server_socket = socket.socket() # get instance # look closely. The bind() function takes tuple as argument server_socket.bind((host, port)) # bind host address and port together # configure how many client the server can listen simultaneously server_socket.listen(2) conn, address = server_socket.accept() # accept new connection print("Connection from: " + str(address)) while True: # receive data stream. it won't accept data packet greater than 1024 bytes client = conn.recv(800000).decode() if not client: # if data is not received break break print("from connected user: "******"PROCESS": print("Procesando HL7...") try: m = parser.parse_message(client) except UnsupportedVersion: m = parser.parse_message(client.replace("n", "r")) f = open("receivedData/message.hl7", "w") f.write(m.value) f.close() if m.msh.msh_3.value == "img": file_like = m.ORU_R01_PATIENT_RESULT.ORU_R01_ORDER_OBSERVATION.ORU_R01_OBSERVATION.OBX.obx_5.value f1 = open("receivedData/hl7image.jpg", "wb") f1.write(base64.b64decode(str.encode(file_like))) f1.close() elif m.msh.msh_3.value == "text": f1 = open("receivedData/hl7owl.owl", "w") f1.write(m.ORU_R01_PATIENT_RESULT.ORU_R01_ORDER_OBSERVATION. ORU_R01_OBSERVATION.OBX.obx_5.value) f1.close() else: print( "No se pudo procesar. El archivo enviado por HL7 no corresponde con img o text." ) server = input(' -> ') conn.send(server.encode()) # send data to the client conn.close() # close the connection
def test_to_mllp(self): test_msg = self._get_test_msg() mllp_msg = '{0}{1}{2}{3}{2}'.format(MLLP_ENCODING_CHARS.SB, test_msg, MLLP_ENCODING_CHARS.CR, MLLP_ENCODING_CHARS.EB) msg = parse_message(test_msg) self.assertEqual(msg.to_mllp(), mllp_msg)
def test_to_mllp_with_trailing(self): test_msg = self._get_test_msg(trailing_children=True) mllp_msg = '{0}{1}{2}{3}{2}'.format(MLLP_ENCODING_CHARS.SB, test_msg, MLLP_ENCODING_CHARS.CR, MLLP_ENCODING_CHARS.EB) msg = parse_message(test_msg) self.assertEqual(msg.to_mllp(trailing_children=True), mllp_msg)
def test_trailing_children(self): test_msg = self._get_test_msg(trailing_children=False) test_msg_with_trailing = self._get_test_msg(trailing_children=True) msg = parse_message(test_msg) self.assertEqual(msg.to_er7(trailing_children=True), test_msg_with_trailing) self.assertEqual(msg.to_er7(trailing_children=False), test_msg)
def test_assign_value_unknown_message(self): msg = _get_test_msg() a = Message() parsed_a = parse_message(msg, validation_level=VALIDATION_LEVEL.QUIET) a.value = msg self.assertEqual(a.name, 'OML_O33') self.assertEqual(a.to_er7(), parsed_a.to_er7())
def parse_pdq_response(er7_message): msg = parse_message(er7_message, message_profile=_PDQ_RES_MP, validation_level=VL.TOLERANT) msg_status = msg.msa.msa_1.value query_status = msg.qak.qak_2.value if msg_status != "AA": return None if query_status == "NF": return [] patients = [] for g in msg.rsp_k21_query_response: patient = { "id": g.pid.pid_3.cx_1.value, "first_name": g.pid.pid_5.xpn_2.value, "last_name": g.pid.pid_5.xpn_1.value, "birth_date": g.pid.pid_7.ts_1.value, "gender": g.pid.pid_8.value, "account_number": g.pid.pid_18.cx_1.value, "birth_place": g.pid.pid_23.value, 'city': g.pid.pid_11.xad_3.value, 'phone': g.pid.pid_13.xtn_1.value, 'mobile': "", 'email': g.pid.pid_13.xtn_4.value, 'certified_email': "", 'active': True } patients.append(patient) return patients
def __init__(self, raw_msg): self.msg = parse_message(raw_msg) logger.debug('{}'.format(type(self.msg))) self.raw_results = self.msg.oul_r22_specimen logger.debug('{}'.format(type(self.raw_results))) self.instrument_info = None self.run_info = None
def test_to_mllp(self): test_msg = self._get_test_msg() mllp_msg = "{0}{1}{2}{3}{2}".format(MLLP_ENCODING_CHARS.SB, test_msg, MLLP_ENCODING_CHARS.CR, MLLP_ENCODING_CHARS.EB) msg = parse_message(test_msg) self.assertEqual(msg.to_mllp(), mllp_msg)
def test_to_mllp_with_trailing(self): test_msg = self._get_test_msg(trailing_children=True) mllp_msg = "{0}{1}{2}{3}{2}".format(MLLP_ENCODING_CHARS.SB, test_msg, MLLP_ENCODING_CHARS.CR, MLLP_ENCODING_CHARS.EB) msg = parse_message(test_msg) self.assertEqual(msg.to_mllp(trailing_children=True), mllp_msg)
def handle(self): line = '' while True: char = self.rfile.read(1) if not char: print('Cliente desconectado') break line += char # verifica se existe alguma mensagem HL7 no buffer message = MLLProtocol.get_message(line) if message is not None: try: # parse the incoming message m = parse_message(message, find_groups=False) print("\n=========================================================================") print("Mensagem recebida com sucesso") print("\nTipo da Mensagem Recebida: ", m.MSH.message_type.to_er7()) print("\nMensagem Recebida de: ", m.MSH.sending_application.to_er7()) print("\nConteudo da mensagem:", repr(m.to_er7())) print("\n=========================================================================") except: print("Falha no Parsing!", repr(message)) if m.MSH.MSH_9.MSH_9_3.to_er7() == 'QBP_Q11': response = responder(m) else: print ("Mensagem recebida irregularmente!") response = "none" self.wfile.write(response) line = ''
def parse_messages(directory, validation_level=VL.STRICT, find_groups=True, limit=-1, output_file=None): exceptions = {VL.QUIET: [], VL.STRICT: []} msg_per_versions = {VL.QUIET: defaultdict(int), VL.STRICT: defaultdict(int)} msg_per_type = {VL.QUIET: defaultdict(int), VL.STRICT: defaultdict(int)} parsing_time = {VL.QUIET : [], VL.STRICT : []} encoding_time = [] files = _get_files(directory)[:limit] if limit != -1 else _get_files(directory) n_messages = {VL.QUIET : 0, VL.STRICT : 0} start = time.time() for f in sorted(files): with open(f) as hl7_file: msg_str = hl7_file.read() msg_str = msg_str.replace('\r\n', '\r') msg_str = msg_str.replace('\n', '\r') error_occurred = False validations = [VL.STRICT, VL.QUIET] if validation_level == VL.QUIET: validations.remove(VL.STRICT) for vl in validations: # it parses QUIET only if the user asked (validation_level == VL.QUIET) or an error occurred if vl == VL.QUIET and (validation_level != VL.QUIET and not error_occurred): continue file_base_name = os.path.basename(hl7_file.name) n_messages[vl] += 1 try: msg_start = time.time() msg = parse_message(msg_str, vl, find_groups=find_groups) msg_end = time.time() msg_per_versions[vl][msg.version] += 1 msg_per_type[vl][msg.msh.msh_9.to_er7()] += 1 parsing_time[vl].append((file_base_name, len(msg.children), msg.msh.msh_9.to_er7(), msg_end - msg_start)) except Exception as e: exceptions[vl].append({'type' : 'parsing', 'ex': e, 'file_name' : f, 'msg' : msg_str}) if vl == VL.STRICT: error_occurred = True try: encoding_start = time.time() msg.to_er7() encoding_end = time.time() encoding_time.append((file_base_name, len(msg.children), msg.msh.msh_9.to_er7(), encoding_end - encoding_start)) except Exception as e: exceptions[vl].append({'type' : 'encoding', 'ex': e, 'file_name' : f, 'msg' : msg_str}) elapsed_time = time.time() - start print_report(n_messages, msg_per_versions, msg_per_type, exceptions, elapsed_time, output_file, parsing_time, encoding_time, validation_level)
def ack_listener(): while True: msgBytes = s.recv(1024) message = msgBytes.decode('utf-8') messageParsed = parse_message(message) print("\nACK RECEIVED") print(messageParsed.value.replace('\r', '\n')) if messageParsed.msh.msh_9.value == "ACK": id = messageParsed.msh.msh_10.value remove_from_wl(id)
def hl7_str_to_dict(s, use_long_name=True): """Convert an HL7 string to a dictionary :param s: The input HL7 string :param use_long_name: Whether or not to user the long names (e.g. "patient_name" instead of "pid_5") :returns: A dictionary representation of the HL7 message """ s = s.replace("\n", "\r") m = parse_message(s) return hl7_message_to_dict(m, use_long_name=use_long_name)
def parse_adt_message(hl7msg: str, r: dict) -> dict: m = parse_message(hl7msg, find_groups=False) identifier_list = list() for pid_3 in m.PID.PID_3: identifier_element = {} if value := pid_3.PID_3_1.value: identifier_element["value"] = value if system := pid_3.PID_3_4.value: identifier_element["system"] = system
def reply(message): """ Parse the incoming message and return the ER7 encoded response :param message: incoming message :return: response encoded to ER7 - it can be a NAK or RSP_K11 message """ print "Received by LIP", repr(message) try: # parse the incoming message m = parse_message(message, find_groups=False) except: print 'parsing failed', repr(message) response = LIP.nak() else: print "Message type:", m.MSH.message_type.to_er7() print "Message content:", repr(m.to_er7()) if m.MSH.MSH_9.MSH_9_3.to_er7() == 'QBP_Q11': # create a new RSP_K11 message response = Message("RSP_K11") response.MSH.MSH_9 = "RSP^K11^RSP_K11" # add MSA segment response.MSA = "MSA|AA" response.MSA.MSA_2 = m.MSH.MSH_10 # create a QAK segment qak = Segment("QAK") qak.qak_1 = m.QPD.QPD_2 qak.qak_2 = "OK" qak.qak_3 = "Q22^Specimen Labeling Instructions^IHE_LABTF" qak.qak_4 = "1" # add the QAK segment to the RSP_K11 message response.add(qak) # copy the QPD segment from the incoming message response.QPD = m.QPD # create a PID segment response.PID.PID_1 = '1' response.PID.PID_5.PID_5_1 = 'PATIENT_SURNAME' response.PID.PID_5.PID_5_2 = 'PATIENT_NAME' response.PID.PID_6 = "19800101" response.PID.PID_7 = "F" # create a SPM segment spm = Segment("SPM") # create an OBR segment obr = Segment("OBR") spm.SPM_1 = '1' spm.SPM_2 = "12345" obr.OBR_4 = "ORDER^DESCRIPTION" # add spm and obr to the RSP_K11 response response.add(spm) response.add(obr) else: response = LIP.nak(m) return response.to_mllp() # encode to ER7
def reply(message): """ Parse the incoming message and return the ER7 encoded response :param message: incoming message :return: response encoded to ER7 - it can be a NAK or RSP_K11 message """ print("Received by LIP", repr(message)) try: # parse the incoming message m = parse_message(message, find_groups=False) except: print('parsing failed', repr(message)) response = LIP.nak() else: print("Message type:", m.MSH.message_type.to_er7()) print("Message content:", repr(m.to_er7())) if m.MSH.MSH_9.MSH_9_3.to_er7() == 'QBP_Q11': # create a new RSP_K11 message response = Message("RSP_K11") response.MSH.MSH_9 = "RSP^K11^RSP_K11" # add MSA segment response.MSA = "MSA|AA" response.MSA.MSA_2 = m.MSH.MSH_10 # create a QAK segment qak = Segment("QAK") qak.qak_1 = m.QPD.QPD_2 qak.qak_2 = "OK" qak.qak_3 = "Q22^Specimen Labeling Instructions^IHE_LABTF" qak.qak_4 = "1" # add the QAK segment to the RSP_K11 message response.add(qak) # copy the QPD segment from the incoming message response.QPD = m.QPD # create a PID segment response.PID.PID_1 = '1' response.PID.PID_5.PID_5_1 = 'PATIENT_SURNAME' response.PID.PID_5.PID_5_2 = 'PATIENT_NAME' response.PID.PID_6 = "19800101" response.PID.PID_7 = "F" # create a SPM segment spm = Segment("SPM") # create an OBR segment obr = Segment("OBR") spm.SPM_1 = '1' spm.SPM_2 = "12345" obr.OBR_4 = "ORDER^DESCRIPTION" # add spm and obr to the RSP_K11 response response.add(spm) response.add(obr) else: response = LIP.nak(m) return response.to_mllp() # encode to ER7
def test_message_inspection_by_group_parsing(self): msg = self._get_multiple_segments_groups_message() message = parse_message(msg) #access first spm_27_1: P2_S1 self.assertEqual(message.oml_o33_specimen[0].spm.spm_27.spm_27_1.to_er7(), 'CONTAINER') #by datatype name instead that by position it is the same than previous one self.assertEqual(message.oml_o33_specimen[0].spm.spm_27.cwe_1.to_er7(), 'CONTAINER') #access to the second order test belonging to the second specimen self.assertEqual(message.oml_o33_specimen[ 1].oml_o33_order.oml_o33_observation_request.oml_o33_prior_result.oml_o33_order_prior[ 1].obr.obr_4.obr_4_1.to_er7(), 'HDL')
def _build_default_response(self): inc_msg = parse_message(self.incoming_message) m = Message("ACK") m.MSH.MSH_9 = "ACK^ACK" m.MSA.MSA_1 = "AR" m.MSA.MSA_2 = inc_msg.MSH.MSH_10 m.ERR.ERR_1 = "%s" % self.error_code m.ERR.ERR_2 = "%s" % self.error_msg return m.to_mllp()
def parse_messages(directory, limit=-1, output_file=None): exceptions = {'QUIET': [], 'STRICT': []} msg_per_versions = {'QUIET': defaultdict(int), 'STRICT': defaultdict(int)} msg_per_type = {'QUIET': defaultdict(int), 'STRICT': defaultdict(int)} parsing_time = {'QUIET' : [], 'STRICT' : []} files = _get_files(directory)[:limit] n_messages = {'QUIET' : 0, 'STRICT' : len(files)} start = time.time() for f in files: with open(f) as hl7_file: msg_str = hl7_file.read() msg_str = msg_str.replace('\r\n', '\r') msg_str = msg_str.replace('\n', '\r') try: msg_start = time.time() msg = parse_message(msg_str, VALIDATION_LEVEL.STRICT) msg_end = time.time() msg_per_versions['STRICT'][msg.version] += 1 msg_per_type['STRICT'][msg.msh.msh_9.to_er7()] += 1 parsing_time['STRICT'].append((len(msg.children), msg_end - msg_start)) except Exception as e: n_messages['QUIET'] += 1 try: msg_start = time.time() msg = parse_message(msg_str, VALIDATION_LEVEL.QUIET) msg_end = time.time() msg_per_versions['QUIET'][msg.version] += 1 msg_per_type['QUIET'][msg.msh.msh_9.to_er7()] += 1 parsing_time['QUIET'].append((len(msg.children), msg_end - msg_start)) exceptions['STRICT'].append({'ex': e, 'file_name' : f, 'msg' : msg_str}) except Exception as e: exceptions['QUIET'].append({'ex': e, 'file_name' : f, 'msg' : msg_str}) elapsed_time = time.time() - start print_report(n_messages, msg_per_versions, msg_per_type, exceptions, elapsed_time, output_file, parsing_time)
def receive(message): # print to stdout the data received print "Received by LB" try: # parse the incoming HL7 message m = parse_message(message, find_groups=False) except: print 'parsing failed', repr(message) else: print "Message type:", m.MSH.message_type.to_er7() print "Message content:", repr(m.to_er7()) surname, name = m.PID.PID_5.family_name.to_er7(), m.PID.PID_5.given_name.to_er7() print "Patient data:", surname, name
def receive(message): # print to stdout the data received print("Received by LB") try: # parse the incoming HL7 message m = parse_message(message, find_groups=False) except: print('parsing failed', repr(message)) else: print("Message type:", m.MSH.message_type.to_er7()) print("Message content:", repr(m.to_er7())) surname, name = m.PID.PID_5.family_name.to_er7( ), m.PID.PID_5.given_name.to_er7() print("Patient data:", surname, name)
def test_assign_value(self): msg = _get_test_msg() a = Message('OML_O33', validation_level=VALIDATION_LEVEL.QUIET) parsed_a = parse_message(msg, validation_level=VALIDATION_LEVEL.QUIET) a.value = msg self.assertEqual(a.to_er7(), parsed_a.to_er7()) b = Message('OML_O33', validation_level=VALIDATION_LEVEL.STRICT) b.value = msg parsed_b = parse_message(msg, validation_level=VALIDATION_LEVEL.STRICT) self.assertEqual(b.to_er7(), parsed_b.to_er7()) self.assertEqual(b.children.indexes.keys(), parsed_b.children.indexes.keys()) c = Message('ADT_A01', validation_level=VALIDATION_LEVEL.QUIET) with self.assertRaises(OperationNotAllowed): c.value = msg msg = msg.replace('^', 'x') with self.assertRaises(OperationNotAllowed): a.value = msg c = Message('OML_O33', version='2.6') with self.assertRaises(OperationNotAllowed): c.value = msg
def ack_listener(): global num global acks_gotten while acks_gotten < num: msgBytes = s.recv(1024) message = msgBytes.decode('utf-8') messageParsed = parse_message(message) if messageParsed.msh.msh_9.value == "ACK": id = messageParsed.msh.msh_10.value print(id, "- Received ACK") received = time.time() update_db(id, received) acks_gotten += 1
def query(host, port): msg = \ 'MSH|^~\&|REC APP|REC FAC|SEND APP|SEND FAC|20110708163513||QBP^Q22^QBP_Q21|111069|D|2.5|||||ITA||EN\r' \ 'QPD|IHE PDQ Query|111069|@PID.5.2^SMITH||||\r' \ 'RCP|I|' # establish the connection sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect((host, port)) # send the message sock.sendall(parse_message(msg).to_mllp().encode('UTF-8')) # receive the answer received = sock.recv(1024*1024) return received finally: sock.close()
def index(request): context = RequestContext(request) if request.method == 'POST': text = request.POST['hl7doc'] m = parse_message(text, 2, True) r = Record() r.msh_9 = m.msh.msh_9.to_er7() r.msh_10 = m.msh.msh_10.to_er7() r.msh_11 = m.msh.msh_11.to_er7() r.msh_12 = m.msh.msh_12.to_er7() r.pid_5 = m.pid.pid_5.to_er7() r.pid_11 = m.pid.pid_11.to_er7() r.evn_2 = m.evn.evn_2.to_er7() r.evn_4 = m.evn.evn_4.to_er7() r.save() return HttpResponseRedirect('/') records = Record.objects.all() return render_to_response('index.html', {'records': records}, context)
def query(host, port, patient_id): """ Estabelecer uma conecção TCP utilizando como parâmetros o endereço e a porta do servidor para enviar uma mensagem de exemplo QBP_Q11 :param host: endereço para conexão :param port: porta para conexão :param patient_id: patient_id para a mensgem de consulta """ # gerando a mensagem QBP_Q11 pacote = enviar(patient_id) # estabelecendo conexão sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect((host, port)) # enviar a mensagem sock.sendall(pacote) # receber a resposta received = sock.recv(1024*1024) mensagem = MLLProtocol.get_message(received) # manipular a resposta try: # parse the incoming HL7 message m = parse_message(mensagem, find_groups=False) except: print 'parsing failed', repr(mensagem) else: print "\n=========================================================================" print "Resposta do Servidor:\n\n" print "\nTipo da Mensagem Recebida: ", m.MSH.message_type.to_er7() print "\nID do paciente: ", m.PID.PID_1.to_er7() print "\nNome do paciente: ", m.PID.PID_5.given_name.to_er7(), m.PID.PID_5.family_name.to_er7() ano = m.PID.PID_6.to_er7() print "\nAno de nascimento: ", ano[0:4] print "\nLocal de nascimento: ", m.PID.PID_23.to_er7() print "\nConteudo da mensagem: ", repr(m.to_er7()) print "\n=========================================================================" finally: sock.close()
def reply(self): if isinstance(self.exc, UnsupportedMessageType): err_code, err_msg = 101, 'Unsupported message' elif isinstance(self.exc, InvalidHL7Message): err_code, err_msg = 102, 'Incoming message is not an HL7 valid message' else: err_code, err_msg = 100, 'Unknown error occurred' parsed_message = parse_message(self.incoming_message) m = Message("ACK") m.MSH.MSH_9 = "ACK^ACK" m.MSA.MSA_1 = "AR" m.MSA.MSA_2 = parsed_message.MSH.MSH_10 m.ERR.ERR_1 = "%s" % err_code m.ERR.ERR_2 = "%s" % err_msg return m.to_mllp()
def index(request): context = RequestContext(request) if request.method=='POST': text = request.POST['hl7doc'] m = parse_message(text,2,True) r = Record() r.msh_9 = m.msh.msh_9.to_er7() r.msh_10 = m.msh.msh_10.to_er7() r.msh_11 = m.msh.msh_11.to_er7() r.msh_12 = m.msh.msh_12.to_er7() r.pid_5 = m.pid.pid_5.to_er7() r.pid_11 = m.pid.pid_11.to_er7() r.evn_2 = m.evn.evn_2.to_er7() r.evn_4 = m.evn.evn_4.to_er7() r.save() return HttpResponseRedirect('/') records = Record.objects.all() return render_to_response('index.html', {'records': records}, context)
def test_parse_message_create_groups(self): msg = self._get_multiple_segments_groups_message() message = parse_message(msg) self.assertEqual(message.children[0].name, 'MSH') self.assertEqual(message.children[1].name, 'OML_O33_PATIENT') self.assertEqual(message.children[2].name, 'OML_O33_SPECIMEN') self.assertEqual(message.children[3].name, 'OML_O33_SPECIMEN') # the first specimen has only one order specimen_1 = message.children[2] self.assertEqual(specimen_1.children[0].name, 'SPM') self.assertEqual(specimen_1.children[1].name, 'OML_O33_ORDER') # the second specimen has three different orders, and the second and third are inside the ORDER PRIOR group specimen_2 = message.children[3] self.assertEqual(specimen_2.children[1].name, 'OML_O33_ORDER') spm_2_order = specimen_2.children[1] self.assertEqual(spm_2_order.children[0].name, 'ORC') self.assertEqual(spm_2_order.children[1].name, 'OML_O33_TIMING') spm_2_obs_req = spm_2_order.oml_o33_observation_request self.assertEqual(spm_2_obs_req.children[0].name, 'OBR') self.assertEqual(spm_2_obs_req.children[1].name, 'OML_O33_PRIOR_RESULT')
def test_parse_message_create_groups(self): msg = self._get_multiple_segments_groups_message() message = parse_message(msg) self.assertEqual(message.children[0].name, 'MSH') self.assertEqual(message.children[1].name, 'OML_O33_PATIENT') self.assertEqual(message.children[2].name, 'OML_O33_SPECIMEN') self.assertEqual(message.children[3].name, 'OML_O33_SPECIMEN') #the first specimen has only one order specimen_1 = message.children[2] self.assertEqual(specimen_1.children[0].name, 'SPM') self.assertEqual(specimen_1.children[1].name, 'OML_O33_ORDER') #the second specimen has three different orders, and the second and third are inside the ORDER PRIOR group specimen_2 = message.children[3] self.assertEqual(specimen_2.children[1].name, 'OML_O33_ORDER') spm_2_order = specimen_2.children[1] self.assertEqual(spm_2_order.children[0].name, 'ORC') self.assertEqual(spm_2_order.children[1].name, 'OML_O33_TIMING') spm_2_obs_req = spm_2_order.oml_o33_observation_request self.assertEqual(spm_2_obs_req.children[0].name, 'OBR') self.assertEqual(spm_2_obs_req.children[1].name, 'OML_O33_PRIOR_RESULT')
def _check_incoming_message(self): """ Controls the incoming HL7 message, after parsing, according to some IHE PDQ message request rules. It checks that: - All query parameters codes and values are correct in the request message - The incoming message contains at least one query parameter - For the birth date query parameter, the date value format is HL7 - compliant - If the Allowed Application Filter is enabled. checks if the MSH_3 field contains a value included in the Allowed_application list table :raises: :exc:`MissingQueryParameters` if the incoming message has not any query parameters (QPD_3 hl7 message field is empty) :raises: :exc:`InvalidQueryParameterCode` if the incoming message has a query parameter code (QPD_3_1) in a not-allowed format :raises: :exc:`MissingQueryParameterValue` if the incoming message has a query parameter (QPD_3_1) correct but without the corrispondent value (QPD_3_2) :raises: :exc:`InvalidDateParameterValue` if the incoming message has a query parameter (QPD_3_1) asking for the patient birth date, but providing a not allowed date format in the value :raise: :exc:`InvalidSendingApplicationParameterValue if the Application Filter is enabled and the MSH_3 field of the incoming message is not included into the Allowed Applications list` """ try: message_profiles_dir = _get_message_profiles_dir() logger.debug("Checking for message profile from dir: %s" % message_profiles_dir) if self.is_pdq_message(): message_profile = load_message_profile(os.path.join(message_profiles_dir, 'pdq_request')) elif self.is_pdqv_message(): message_profile = load_message_profile(os.path.join(message_profiles_dir, 'pdqv_request')) else: raise MessageProfileNotFound() self.msg = parse_message(self.raw_msg, validation_level=VALIDATION_LEVEL.STRICT, message_profile=message_profile) except MessageProfileNotFound, e: # NO PDQ logger.error("No message profile found for message: %s -> %s" % (self.raw_msg, str(e))) raise PDQMessageProfileNotFound
def test_parse_message_ignoring_groups(self): msh = 'MSH|^~\&|SENDING APP|SENDING FAC|REC APP|REC FAC|20080115153000||ADT^A01^ADT_A01|0123456789|P|2.5||||AL\r' evn = 'EVN||20080115153000||AAA|AAA|20080114003000\r' pid = 'PID|1||123-456-789^^^HOSPITAL^MR||SURNAME^NAME^A|||M|||1111 SOMEWHERE STREET^^SOMEWHERE^^^USA||555-555-2004~444-333-222|||M\r' nk1 = 'NK1|1|WOMAN^WIFE|SPO|1111 SOMEWHERE STREET^^SOMEWHERE^^^USA\r' pv1 = 'PV1|1|I|PATIENT WARD|U||||^REFERRING^DOCTOR^^MD|^CONSULTING^DOCTOR|CAR||||2|A0|||||||||||||||||||||||||||||2013\r' in1 = 'IN1|1|INSURANCE PLAN ID^PLAN DESC|COMPANY ID|INSURANCE COMPANY, INC.|5555 INSURERS STREET^^SOMEWHERE^^^USA||||||||||||||||||||||||||||||||||||||||||||555-44-3333' str_message = msh+evn+pid+nk1+pv1+in1 message = parse_message(str_message, find_groups=False) self.assertEqual(message.children[0].name, 'MSH') self.assertEqual(message.children[1].name, 'EVN') self.assertEqual(message.children[2].name, 'PID') self.assertEqual(message.children[3].name, 'NK1') self.assertEqual(message.children[4].name, 'PV1') self.assertEqual(message.children[5].name, 'IN1') self.assertEqual(message.pid.pid_5.pid_5_1.fn_1.to_er7(), 'SURNAME') self.assertEqual(message.evn.evn_5.xcn_1.to_er7(), message.evn.evn_5.evn_5_1.to_er7()) m_string = message.to_er7() self.assertEqual(m_string, str_message)
def test_parse_message_ignoring_groups(self): msh = 'MSH|^~\&|SEND APP|SEND FAC|REC APP|REC FAC|20080115153000||ADT^A01^ADT_A01|0123456789|P|2.5||||AL\r' evn = 'EVN||20080115153000||AAA|AAA|20080114003000\r' pid = 'PID|1||123-456-789^^^HOSPITAL^MR||SURNAME^NAME^A|||M|||1111 SOMEWHERE^^SOMEWHERE^^^USA||555~444|||M\r' nk1 = 'NK1|1|WOMAN^WIFE|SPO|1111 SOMEWHERE^^SOMEWHERE^^^USA\r' pv1 = 'PV1|1|I|PATIENT WARD|U||||^REFER^DOCTOR^^MD|^CONSUL^DOC|CAR||||2|A0|||||||||||||||||||||||||||||2013\r' in1 = 'IN1|1|INSURANCE PLAN ID^PLAN DESC|COMPANY ID|INS CNY, INC.|5555 INSURERS STREET^^SOMEWHERE^^^USA' str_message = msh + evn + pid + nk1 + pv1 + in1 message = parse_message(str_message, find_groups=False) self.assertEqual(message.children[0].name, 'MSH') self.assertEqual(message.children[1].name, 'EVN') self.assertEqual(message.children[2].name, 'PID') self.assertEqual(message.children[3].name, 'NK1') self.assertEqual(message.children[4].name, 'PV1') self.assertEqual(message.children[5].name, 'IN1') self.assertEqual(message.pid.pid_5.pid_5_1.fn_1.to_er7(), 'SURNAME') self.assertEqual(message.evn.evn_5.xcn_1.to_er7(), message.evn.evn_5.evn_5_1.to_er7()) m_string = message.to_er7() self.assertEqual(m_string, str_message)
def lambda_handler(event, context): hl7_message = event['hl7'] message = parse_message(hl7_message) response = { 'PatientID': message.pid.pid_3.pid_3_1.value, 'City': message.pid.pid_11.pid_11_3.value, 'Country': message.pid.pid_11.pid_11_6.value, 'DateOfBirth': message.pid.pid_7.value, 'FirstName': message.pid.pid_5.pid_5_2.value, 'Gender': message.pid.pid_8.value, 'LastName': message.pid.pid_5.pid_5_1.value, 'MaritalStatus': message.pid.pid_16.value, 'MiddleName': ' ', 'ResidenceNumber': message.pid.pid_11.pid_11_1.value, 'Salutation': message.pid.pid_5.pid_5_3.value, 'State': message.pid.pid_11.pid_11_4.value, 'ZipCode': message.pid.pid_11.pid_11_5.value, 'Allergies': message.al1.al1_3.al1_3_2.value } return response
def parse_messages(directory, validation_level=VL.STRICT, find_groups=True, limit=-1, output_file=None, message_profile=None): exceptions = {VL.TOLERANT: [], VL.STRICT: []} msg_per_versions = { VL.TOLERANT: defaultdict(int), VL.STRICT: defaultdict(int) } msg_per_type = {VL.TOLERANT: defaultdict(int), VL.STRICT: defaultdict(int)} parsing_time = {VL.TOLERANT: [], VL.STRICT: []} encoding_time = [] files = _get_files(directory)[:limit] if limit != -1 else _get_files( directory) n_messages = {VL.TOLERANT: 0, VL.STRICT: 0} mp = load_message_profile( message_profile) if message_profile is not None else None start = time.time() for f in sorted(files): with open(f) as hl7_file: msg_str = hl7_file.read() msg_str = msg_str.replace('\r\n', '\r') msg_str = msg_str.replace('\n', '\r') error_occurred = False validations = [VL.STRICT, VL.TOLERANT] if validation_level == VL.TOLERANT: validations.remove(VL.STRICT) for vl in validations: # it parses TOLERANT only if the user asked (validation_level == VL.TOLERANT) # or an error occurred if vl == VL.TOLERANT and (validation_level != VL.TOLERANT and not error_occurred): continue file_base_name = os.path.basename(hl7_file.name) try: msg_start = time.time() msg = parse_message(msg_str, vl, find_groups=find_groups, message_profile=mp) msg_end = time.time() msg_per_versions[vl][msg.version] += 1 msg_per_type[vl][msg.msh.msh_9.to_er7()] += 1 parsing_time[vl].append( (file_base_name, len(msg.children), msg.msh.msh_9.to_er7(), msg_end - msg_start)) except MessageProfileNotFound: continue except InvalidEncodingChars: if mp is None: exceptions[vl].append({ 'type': 'parsing', 'ex': e, 'file_name': f, 'msg': msg_str }) if vl == VL.STRICT: error_occurred = True else: continue except Exception as e: exceptions[vl].append({ 'type': 'parsing', 'ex': e, 'file_name': f, 'msg': msg_str }) if vl == VL.STRICT: error_occurred = True n_messages[vl] += 1 try: encoding_start = time.time() msg.to_er7() encoding_end = time.time() encoding_time.append((file_base_name, len(msg.children), msg.msh.msh_9.to_er7(), encoding_end - encoding_start)) except Exception as e: exceptions[vl].append({ 'type': 'encoding', 'ex': e, 'file_name': f, 'msg': msg_str }) elapsed_time = time.time() - start print_report(n_messages, msg_per_versions, msg_per_type, exceptions, elapsed_time, output_file, parsing_time, encoding_time, validation_level, message_profile)
def from_string(txt): """ Initialize a message from string. """ txt = txt.replace('\n', '\r') return HL7Message(parse_message(txt, find_groups=False))
passwd="", database="requests" ) print("Connected to",str(mydb)) try: while True: c, addr = serversocket.accept() print("New connection from",addr) while True: msgBytes = c.recv(1024) if not msgBytes: break else: message = msgBytes.decode('utf-8') messageParsed = parse_message(message) print(messageParsed.value.replace('\r','\n')) id = messageParsed.ORU_R01_PATIENT_RESULT.ORU_R01_ORDER_OBSERVATION.orc.orc_1.value worklist = messageParsed.msh.msh_10.value status = messageParsed.ORU_R01_PATIENT_RESULT.ORU_R01_ORDER_OBSERVATION.ORU_R01_OBSERVATION.obx.obx_11.value report = messageParsed.ORU_R01_PATIENT_RESULT.ORU_R01_ORDER_OBSERVATION.ORU_R01_OBSERVATION.obx.obx_5.value print(str(status)) update_db(id,status,report) hl7 = core.Message("ACK", validation_level=VALIDATION_LEVEL.STRICT) hl7.msh.msh_3 = "RequestsServer" hl7.msh.msh_4 = "RequestsServer" hl7.msh.msh_5 = "ExamsClient"
s.listen(5) # Now wait for client connection. cnx = mysql.connector.connect(user='******', password='******', host='127.0.0.1', database='exames') while True: c, addr = s.accept() # Establish connection with client. print 'Got connection from', addr line = "" ids = [] while not (line.endswith("$")): line += c.recv(1024) print(line.replace('\r', '\n')) mensagens = line[:-1].split("$") for m in mensagens: message = parse_message(m) print message.children # Get Patient Info iddoente = message.ORM_O01_PATIENT.pid.pid_2.value numprocesso = message.ORM_O01_PATIENT.pid.pid_3.value nome = message.ORM_O01_PATIENT.pid.pid_5.value morada = message.ORM_O01_PATIENT.pid.pid_11.value telefone = message.ORM_O01_PATIENT.pid.pid_13.value # Get Message Content idpedido = message.ORM_O01_ORDER.ORC.orc_2.value estado = message.ORM_O01_ORDER.orc.orc_1.value mdata = message.ORM_O01_ORDER.ORC.orc_10.value observacoes = message.ORM_O01_ORDER.ORM_O01_ORDER_DETAIL.ORM_O01_ORDER_CHOICE.OBR.obr_13.value idepisodio = message.ORM_O01_ORDER.ORM_O01_ORDER_DETAIL.ORM_O01_ORDER_CHOICE.OBR.obr_4.value relatorio = message.ORM_O01_ORDER.ORM_O01_ORDER_DETAIL.ORM_O01_ORDER_CHOICE.OBR.obr_12.value if estado == "CN":
def test_parse_message_incomplete_structure(self): m = parse_message('MSH|^~\&|SENDING APP|SENDING FAC|REC APP|REC FAC|20080115153000||ADT^|')
def test_parse_version_27_message_no_truncation(self): m = parse_message(self.rsp_k21_27_no_truncation) self.assertEqual(m.msh.msh_2.to_er7(), '^~\\&') self.assertNotIn('TRUNCATION', m.encoding_chars) self.assertEqual(m.to_er7(), self.rsp_k21_27_no_truncation)
def test_parse_message_with_repetition_segments_and_groups(self): msg = self._get_multiple_segments_groups_message() parse_message(msg)
def _create_message(self, msg_str): return parse_message(msg_str)
def test_parse_message_missing_structure(self): msh = 'MSH|^~\&|SEND APP|SEND FAC|REC APP|REC FAC|20080115153000|||0123456789|P|2.6||||AL\r' pid = 'PID|1||123-456-789^^^HOSPITAL^MR||SURNAME^NAME^A|||M|||1111 SOMEWHERE^^SOMEWHERE^^^USA||555~444|||M\r' msg = msh + pid parse_message(msg)
def test_parse_unknown_message_strict(self): message = 'MSH|^~\&|SENDING APP|SENDING FAC|REC APP|REC FAC|20080115153000||ADT^A01^ADT_A01|0123456789|P|2.6||||AL\r' parse_message(message, validation_level=VALIDATION_LEVEL.STRICT) message = 'MSH|^~\&|SENDING APP|SENDING FAC|REC APP|REC FAC|20080115153000|||0123456789|P|2.6||||AL\r' self.assertRaises(OperationNotAllowed, parse_message, message, validation_level=VALIDATION_LEVEL.STRICT)
def test_parse_message_incomplete_structure(self): m = parse_message('MSH|^~\&|SEND APP|SEND FAC|REC APP|REC FAC|20080115153000||ADT^|')
def test_parse_message_missing_version(self): m = parse_message('MSH|^~\&|SEND APP|SEND FAC|REC APP|REC FAC|20080115153000||ADT^A01^ADT_A01||')
def _create_message(self, msg_str): return parse_message(msg_str, message_profile=self.rsp_k21_mp)
buff += sock.recv(1) return buff[:-2].decode() if __name__ == '__main__': listenerSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) listenerSocket.bind(('', 9999)) print("listening on socket") listenerSocket.listen(1) inSock, addr = listenerSocket.accept() #inSock.settimeout(5.0) print("Got inbound connection from {}".format(addr)) while True: oneMsg = receiveOneMsg(inSock) try: m = parse_message(oneMsg) try: msgType = m.children.get("MSH").children.get("MSH_9").value if msgType == "ACK^R41": print("Got ACK {}".format(pretty(m))) elif msgType == "ORU^R40^ORU_R40": seg1 = _getObxSegment(m, 1) alarmTypeTxt = seg1.children.get("OBX_3").value answer = Message(version="2.7") if alarmTypeTxt == "196614^MDC_EVT_ACTIVE^MDC": # answer with ack print("************ Got Heartbeat ************") print("Full message {}: \n{}".format( datetime.now(), pretty(m))) answer.msh.children.get("MSH_9").value = "ACK^R40" answer.msa.children.get("MSA_1").value = "CA"
def __init__(self, message): self.dao = DAO() msg = parse_message(message, message_profile=self.REQ_MP) super(PDQHandler, self).__init__(msg)
# Michael Sarfati ([email protected]), June 20, 2015 # http://msarfati.wordpress.com from hl7apy import parser from hl7apy.exceptions import UnsupportedVersion hl7 = open('sample.hl7', 'r').read() try: m = parser.parse_message(hl7) except UnsupportedVersion: m = parser.parse_message(hl7.replace("\n", "\r")) import datetime incoming_hl7 = { "type": m.msh.msh_9.value, "client_app": m.msh.msh_3.value, "client_fac": m.msh.msh_4.value, "control_id": m.msh.msh_10.value, "process_id": m.msh.msh_11.value, "timestamp": datetime.datetime.strptime(m.msh.msh_7.value, "%Y%m%d%H%M%S%f"), "hl7": m, }
def test_parse_message_missing_version(self): m = parse_message('MSH|^~\&|SENDING APP|SENDING FAC|REC APP|REC FAC|20080115153000||ADT^A01^ADT_A01||')
def test_parse_version_27_message(self): m = parse_message(self.rsp_k21_27) self.assertEqual(m.msh.msh_2.to_er7(), '^~\\&#') self.assertEqual(m.encoding_chars['TRUNCATION'], '#') self.assertEqual(m.to_er7(), self.rsp_k21_27)