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 send_pdq_request(patient_id): try: host, port = settings.MLLP_HOST, settings.MLLP_PORT except AttributeError: raise AttributeError("Couldn't find MLLP_HOST or MLLP_PORT in the settings file. Did you set them?") msg = Message("QBP_Q21", reference=_PDQ_REQ_MP) msh_9 = "QBP^Q22^QBP_Q21" msg.msh.msh_3 = "MOST CLIENT" msg.msh.msh_4 = "MOST DEMOGRAPHICS" msg.msh.msh_5 = "MOST SERVER" msg.msh.msh_6 = "MOST DEMO" msg.msh.msh_9 = msh_9 msg.msh.msh_10 = uuid.uuid4().hex[:20] msg.msh.msh_11 = "P" msg.msh.msh_17 = "ITA" msg.msh.msh_18 = "UTF-8" msg.msh.msh_19 = "IT" msg.qpd.qpd_1 = "IHE PDQ Query" msg.qpd.qpd_2 = uuid.uuid4().hex[:20] msg.qpd.add_field("qpd_3").value = "@PID.3.1^{}".format(patient_id) msg.rcp.rcp_1 = "I" res = send_hl7_message(host, port, msg.to_mllp()) return parse_pdq_response(res)
def ack(self, resp_type='AA'): """ Build ACK response for incoming message. :type resp_type: str :param resp_type: 'AA' for ACK, 'AR' for Reject, 'AE' for Application Error :rtype: HL7apy.core.Message :return: ACK ('AA') or NAK ('AE', 'AR') message """ resp_types = ('AA', 'AR', 'AE') if resp_type not in resp_types: raise ValueError( "Invalid ACK type. Expected one of: {}".format(resp_types)) resp = Message('ACK', version='2.5.1') resp.msh.msh_3 = 'LIS' resp.msh.msh_4 = 'LIS Facility' resp.msh.msh_5 = self.msg.msh.msh_3 resp.msh.msh_6 = Config.LABNAME resp.msh.msh_9 = 'ACK^R22^ACK' resp.msh.msh_10 = self.run_info.msg_guid resp.msh.msh_11 = 'P' resp.msh.msh_12 = '2.5.1' resp.msh.msh_18 = 'UNICODE UTF-8' resp.msh.msh_21 = 'LAB-29^IHE' resp.add_segment('MSA') resp.msa.msa_1 = resp_type resp.msa.msa_2 = self.run_info.msg_guid if resp_type != 'AA': pass end_resp = add_mllp_frame(resp.to_er7()) assert isinstance(end_resp, bytes) return end_resp
def test_delete_group(self): m = Message('OML_O33', validation_level=VALIDATION_LEVEL.QUIET) g = Group ('OML_O33_PATIENT') m.add(g) self.assertEqual(m.oml_O33_patient.name, 'OML_O33_PATIENT' ) del m.oml_o33_patient self.assertFalse(g in m.children)
def test_add_segment_to_message_mix(self): a = Message('OML_O33', validation_level=VALIDATION_LEVEL.QUIET) msh = Segment('MSH', validation_level=VALIDATION_LEVEL.QUIET) pid = Segment('PID', validation_level=VALIDATION_LEVEL.QUIET) g = Group('OML_O33_PATIENT') g.add(pid) a.add(msh) a.add(g)
def _create_test_message(self, msh_values): """ Create a test message - RSP_K11 - with only the msh segment. The msh is filled with the sent in input """ msg = Message('RSP_K11') msg.msh = self._get_msh(msh_values) return msg
def test_msg_to_string_empty(self): """ It tests the to_er7 message for an empty message """ from datetime import datetime msg = Message('RSP_K11') self.assertRegexpMatches(msg.to_er7(), 'MSH|^~\\&|||||d+|||||2.5')
def test_assign_value_traversal(self): segment_str = 'PID|1||123-456-789^^^HOSPITAL^MR||SURNAME^NAME^A|||M|||1111 SOMEWHERE STREET^^SOMEWHERE^^^USA||555-555-2004~444-333-222|||M\r' m1 = Message('OML_O33') m2 = Message('OML_O33') m1.pid.value = segment_str m2.pid.value = segment_str self.assertEqual(m1.to_er7(), m2.to_er7())
def test_msg_to_string_empty(self): """ It tests the to_er7 message for an empty message """ from datetime import datetime msg = Message('RSP_K11') self.assertEqual(msg.to_er7(), 'MSH|^~\\&|||||%s|||||2.5' %datetime.strftime(datetime.now(), '%Y%m%d%H%M%S') )
def _build_default_response(self): m = Message("ACK") m.MSH.MSH_9 = "ACK^ACK" m.MSA.MSA_1 = "AR" m.MSA.MSA_2 = "" m.ERR.ERR_1 = "%s" % self.error_code m.ERR.ERR_2 = "%s" % self.error_msg return m.to_mllp()
def build_error_response(self, error_msg): m = Message("ACK") m.MSH.MSH_9 = "ACK^ACK" m.MSA.MSA_1 = "AR" m.MSA.MSA_2 = self.msg.MSH.MSH_10 if self.msg else "" m.ERR.ERR_1 = "100" m.ERR.ERR_2 = error_msg return m.to_mllp()
def responder(m): # cria uma mensagem de resposta RSP_K11 response = Message("RSP_K11") response.MSH.MSH_9 = "RSP^K11^RSP_K11" response.MSA = "MSA|AA" response.MSA.MSA_2 = m.MSH.MSH_10 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" response.add(qak) response.QPD = m.QPD response.PID.PID_1 = '1' response.PID.PID_5.PID_5_1 = 'CUNHA' response.PID.PID_5.PID_5_2 = 'JOSE' response.PID.PID_6 = "19800101" response.PID.PID_7 = "F" response.PID.PID_23 = "Brasil" spm = Segment("SPM") obr = Segment("OBR") spm.SPM_1 = '1' spm.SPM_2 = "12345" obr.OBR_4 = "ORDER^DESCRIPTION" response.add(spm) response.add(obr) return response.to_mllp()
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 enviar(patient_id): # cria uma mensagem de consulta QBP_Q11 de acordo com o id do paciente m = Message("QBP_Q11") m.MSH.sending_application = "Cliente" m.MSH.receiving_application = "Servidor" m.MSH.MSH_9 = "QBP^SLI^QBP_Q11" m.MSH.MSH_10 = uuid.uuid4().hex m.QPD.QPD_1 = "SLI^Specimen Labeling Instructions^IHE_LABTF" m.QPD.query_tag = uuid.uuid4().hex m.QPD.QPD_3 = patient_id m.RCP = "RCP|I||R" return m.to_mllp()
def send(patient_id): # create a QBP_Q11 query message for the given patient_id m = Message("QBP_Q11") m.MSH.sending_application = "LB module" # same as m.msh.msh_3 m.MSH.receiving_application = "LIP module" # same as m.msh.msh_5 m.MSH.MSH_9 = "QBP^SLI^QBP_Q11" m.MSH.MSH_10 = uuid.uuid4().hex m.QPD.QPD_1 = "SLI^Specimen Labeling Instructions^IHE_LABTF" m.QPD.query_tag = uuid.uuid4().hex m.QPD.QPD_3 = patient_id m.RCP = "RCP|I||R" return m.to_mllp()
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 readExampleHL7(): m = Message() fl = "" with open(fileorig, 'r') as fd: for line in fd.readlines(): fl = fl + "\r" + line m = pm(fl) return m
def test_to_string_msh_field(self): m = Message('OML_O33') msh = m.msh self.assertEqual(msh.msh_1.to_er7(), '|') self.assertEqual(msh.msh_2.to_er7(), '^~\\&') msh_1 = Field('MSH_1') msh_2 = Field('MSH_2') self.assertRaises(IndexError, msh_1.to_er7) self.assertRaises(IndexError, msh_2.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 genACK(msg, encoding): try: m = pm(msg.decode(encoding)) res = Message('RSP_K11') res.MSH.MSH_9 = 'RSP^K11^RSP_K11' res.MSA = "MSA|AA" res.MSA.MSA_2 = m.MSH.MSH_10 except AttributeError as e: print("Impossible to generate ACK: {0}".format(e)) res = Message('RSP_K11') res.MSH.MSH_9 = 'RSP^K11^RSP_K11' res.MSA = "MSA|AA" except: print("Error trying to generate ACK: ", sys.exc_info()[0]) res = Message('RSP_K11') res.MSH.MSH_9 = 'RSP^K11^RSP_K11' res.MSA = "MSA|AA" finally: return res.to_mllp()
def test_to_string_msh_field_v27(self): for v in ('2.7', '2.8', '2.8.1', '2.8.2'): m = Message('OML_O33', version=v) msh = m.msh self.assertEqual(msh.msh_1.to_er7(), '|') self.assertEqual(msh.msh_2.to_er7(), '^~\\&#') msh_1 = Field('MSH_1') msh_2 = Field('MSH_2') self.assertRaises(IndexError, msh_1.to_er7) self.assertRaises(IndexError, msh_2.to_er7)
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 _create_hl7_message(message_name: str, message_type: str) -> Message: hl7_set_version("2.5.1") m = Message(message_name) msg_datetime = datetime.now().strftime("%Y%m%d%H%M%S") m.MSH.MSH_7 = msg_datetime m.MSH.MSH_9 = message_type m.MSH.MSH_10 = uuid4().hex m.MSH.MSH_11 = "T" m.MSH.MSH_16 = "AL" return m
def test_to_string_msh_field_v27_no_truncation(self): for v in ('2.7', '2.8', '2.8.1', '2.8.2'): m = Message('OML_O33', encoding_chars=DEFAULT_ENCODING_CHARS, version=v) msh = m.msh self.assertEqual(msh.msh_1.to_er7(), '|') self.assertEqual(msh.msh_2.to_er7(), '^~\\&') msh_1 = Field('MSH_1') msh_2 = Field('MSH_2') self.assertRaises(IndexError, msh_1.to_er7) self.assertRaises(IndexError, msh_2.to_er7)
def _create_response(self, ack_code, query_ack_code, patients): res = Message('RSP_K21', reference=self.RES_MP) res.msh.msh_5 = self.incoming_message.msh.msh_3 res.msh.msh_6 = self.incoming_message.msh.msh_4 res.msh.msh_7.ts_1 = DTM(datetime.datetime.now()) res.msh.msh_9 = 'RSP^K22^RSP_K21' res.msh.msh_10 = uuid.uuid4().hex # MSA creation res.msa.msa_1 = ack_code res.msa.msa_2 = self.incoming_message.msh.msh_10.msh_10_1 # QAK creation res.qak.qak_1 = self.incoming_message.qpd.qpd_2 res.qak.qak_2 = 'OK' if len(patients) > 0 else 'NF' res.qak.qak_4 = str(len(patients)) # QPD creation res.qpd = self.incoming_message.qpd # RSP_K21_QUERY_RESPONSE creation res.add_group('rsp_k21_query_response') g = res.rsp_k21_query_response for i, p in enumerate(patients): # add a pid segment for every patient g.add_segment('PID') g.pid[i].pid_3.cx_1, g.pid[i].pid_5.xpn_1, g.pid[i].pid_5.xpn_2 = p[:] return res.to_mllp()
def nak(message): """ Build a NAK response for the incoming message :param message: incoming message :return: a NAK message """ response = Message("ACK") response.MSH.MSH_9 = "ACK" response.MSA.MSA_1 = "AE" response.MSA.MSA_2 = message.MSH.MSH_10 response.MSA.MSA_3 = "Message type not supported" return response
def _create_res(self, ack_code, patients): res = Message('RSP_K21', reference=self.RES_MP) r, q = res.msh, self.incoming_message.msh r.msh_5, r.msh_6 = q.msh_3, q.msh_4 res.msh.msh_5 = self.incoming_message.msh.msh_3 res.msh.msh_6 = self.incoming_message.msh.msh_4 r.msh_7.ts_1 = DTM(datetime.datetime.now()) r.msh_9 = 'RSP^K22^RSP_K21' r.msh_10 = uuid.uuid4().hex r, q = res.msa, self.incoming_message.msh r.msa_1 = ack_code r.msa_2 = q.msh_10.msh_10_1 r, q = res.qak, self.incoming_message.qpd r.qak_1 = q.qpd_2 r.qak_2 = ('OK' if len(patients) > 0 else 'NF') r.qak_4 = str(len(patients)) res.qpd = self.incoming_message.qpd g = res.add_group('rsp_k21_query_response') for i, p in enumerate(patients): s = g.add_segment('PID') s.pid_1 = str(i) s.pid_3.cx_1 = p["IDENTIFIER"] s.pid_3.cx_4 = "master" s.pid_5 = "%s^%s" % (p["SURNAME"], p["NAME"]) s.pid_7.ts_1 = p["DATETIME_OF_BIRTH"] s.pid_8 = p["ADMINISTRATIVE_SEX"] s.pid_11.xad_3 = p["CITY"] s.pid_13.xtn_1 = p["PHONE"] s.pid_13.xtn_4 = p["EMAIL"] s.pid_18.cx_1 = p["ACCOUNT_NUMBER"] s.pid_23 = p["BIRTH_PLACE"] return res
def make_hl7(filename): messages = [] with open(filename, newline='', encoding='utf-8-sig') as f: reader = csv.reader(f, delimiter=',', quotechar='|') for row in reader: m = Message("ADT_A01", version='2.7') m.msh.msh_3 = row[0] m.pid.pid_3.pid_3_1 = row[1] m.pid.pid_3.pid_3_2 = row[2] m.pid.pid_3.pid_3_3 = row[3] m.pid.pid_3.pid_3_4 = row[4] m.pid.pid_5.pid_5_1 = row[5] m.pid.pid_5.pid_5_2 = row[6] m.pid.pid_5.pid_5_3 = row[7] messages.append(m) return messages
def test_assign_wrong_segment_to_known_position(self): a = Message('OML_O33', validation_level=VALIDATION_LEVEL.STRICT) b = Message('OML_O33') with self.assertRaises(ChildNotValid): a.msh = Segment('SPM') with self.assertRaises(ChildNotValid): a.pid = 'EVN||20080115153000||||20080114003000' with self.assertRaises(ChildNotValid): b.msh = Segment('SPM') with self.assertRaises(ChildNotValid): b.pid = 'EVN||20080115153000||||20080114003000'
def _create_message(self, results, ack_code): """ Creates the final RSP_K21 response message. If no errors occurred and some results have been found, the message will carry as many different PID segments as the number of the results. :type: results ``list`` :param: results a list providing the Gnuhealth ORM query results :type: ack_code ``str`` :param: ack_code it is the ack:code to be put in the MSA segment. If no errors occurred, the code wull be of positive ACK (AA); else, one of the negative acks (AE, AR) :return: an hl7apy ``Message`` class instance, which is the final RSP_K21 message """ try: qry_ack_code = 'OK' if len(results) == 0: qry_ack_code = 'NF' is_pdqv = self.is_pdqv_message() logger.debug("Creating response message...") if is_pdqv: message_profile = load_message_profile(os.path.join(_get_message_profiles_dir(), "pdqv_response")) message_structure = PDQV_MESSAGE_STRUCTURE else: message_profile = load_message_profile(os.path.join(_get_message_profiles_dir(), "pdq_response")) message_structure = PDQ_MESSAGE_STRUCTURE message = Message(message_structure, version='2.5', validation_level=VALIDATION_LEVEL.STRICT, reference=message_profile) self._set_msh(message, is_pdqv) msa = message.add_segment("MSA") msa.msa_1 = ack_code msa.msa_2 = self.msg.msh.msh_10.msh_10_1 qak = message.add_segment("QAK") qak.qak_1 = self.msg.qpd.qpd_2 qak.qak_2 = qry_ack_code qak.qak_4.qak_4_1 = str(len(results)) # total results qak.qak_5.qak_5_1 = str(len(results)) # sent results qak.qak_6.qak_6_1 = "0" # remaining results message.add_segment("QPD") message.qpd = self.msg.qpd message = self._create_pdq_res_list(message, message_structure, results) return message except Exception, e: logger.error('Error during Message Creation, %s' % e)
def parse_message(message, validation_level=None, find_groups=True, reference=None): """ Parse the given ER7-encoded message and return an instance of :class:`hl7apy.core.Message`. :type message: ``basestring`` :param message: the ER7-encoded message to be parsed :param validation_level: the validation level. Possible values are those defined in :class:`hl7apy.consts.VALIDATION_LEVEL` class or ``None`` to use the default validation level (see :func:`hl7apy.set_default_validation_level`) :type find_groups: ``bool`` :param find_groups: if ``True``, automatically assign the segments found to the appropriate :class:`hl7apy.core.Group` instances. If ``False``, the segments found are assigned as children of the :class:`hl7apy.core.Message` instance :return: an instance of :class:`hl7apy.core.Message` >>> message = "MSH|^~\&|GHH_ADT||||20080115153000||OML^O33^OML_O33|0123456789|P|2.5||||AL\\rPID|1||566-554-3423^^^GHH^MR||EVERYMAN^ADAM^A|||M|||2222 HOME STREET^^ANN ARBOR^MI^^USA||555-555-2004|||M\\r" >>> m = parse_message(message) >>> print m <Message OML_O33> >>> print m.msh.sending_application.to_er7() GHH_ADT >>> print m.children [<Segment MSH>, <Group OML_O33_PATIENT>] """ message = message.lstrip() encoding_chars, message_structure, version = get_message_info(message) try: m = Message(name=message_structure, version=version, validation_level=validation_level, encoding_chars=encoding_chars) except InvalidName: m = Message(version=version, validation_level=validation_level, encoding_chars=encoding_chars) children = parse_segments(message, m.version, encoding_chars, validation_level) if m.name is not None and find_groups: m.children = [] create_groups(m, children, validation_level) else: m.children = children if Validator.is_strict(validation_level): m.validate() return m
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 test_assign_value_traversal(self): m1 = Message('OML_O33') m2 = Message('OML_O33') m1.oml_o33_specimen.value = self.oml_o33_specimen m2.oml_o33_specimen = self.oml_o33_specimen self.assertEqual(m1.to_er7(), m2.to_er7())
def __init__(self): self._myMsgControlIdIter = 0 self._ORU_R40 = Message(version="2.6")
def test_delete_segment(self): m = Message('OML_O33') pid = Segment('PID') m.add(pid) del m.pid self.assertFalse(pid in m.children)
def test_delete_component(self): m = Message('OML_O33') m.pid = 'PID|||||bianchi^mario|||' pid51 = m.pid.pid_5.pid_5_1 del m.pid.pid_5.pid_5_1
class PCD04Message: HeartbeatAlarmType = "196614^MDC_EVT_ACTIVE^MDC" def getMessage(self): return self._ORU_R40 def __init__(self): self._myMsgControlIdIter = 0 self._ORU_R40 = Message(version="2.6") def createPCD04Message(self, AssignedPatientLocation, EquipII, PatientIdList, PatientName, PatientDoB, PatientSex, AlertType, AlertText, AlertPhase, AlertKindPrioStr, SrcContainmentTreeId, ObsType, ObsValue, ObsValueType, ObsUnit, UniqueAlertUuid, AlertKind, ObsDetTime=None, AlertCounter=0, AlertState="active", AlertInactivationState="enabled", SendingFacility="IHE_AR", ReceivingApplication=None, ProcessingId="D", MdsType="", VmdType=""): messageTime = datetime.now().astimezone() messageTimeStr = messageTime.strftime("%Y%m%d%H%M%S%z") self.createMshSegmentAcm(messageTimeStr, SendingFacility, ReceivingApplication, ProcessingId) self.createPidSegmentAcm(PatientIdList, PatientName, PatientDoB, PatientSex) self.createPv1SegmentAcm(AssignedPatientLocation) self._EquipII = EquipII self.createObrSegmentAcm(messageTimeStr, UniqueAlertUuid, AlertCounter) self._obxCount = 0 MdsTree = "{}.0.0".format(SrcContainmentTreeId.split(".")[0]) VmdTree = "{}.{}.0".format( SrcContainmentTreeId.split(".")[0], SrcContainmentTreeId.split(".")[1]) #AlertTree = SrcContainmentTreeId.split('.')[2] self.createObxSegmentAcm(0, MdsType, ObsValueType="", CTP=MdsTree) self.createObxSegmentAcm(0, VmdType, ObsValueType="", CTP=VmdTree) self.createObxSegmentAcm(1, AlertType, AlertText, CTP=SrcContainmentTreeId) self.createObxSegmentAcm(2, ObsType, ObsValue, ObsValueType=ObsValueType, ObsUnit=ObsUnit, ObsTimeStr=ObsDetTime, CTP=SrcContainmentTreeId) self.createObxSegmentAcm(3, "68481^MDC_ATTR_EVENT_PHASE^MDC", AlertPhase, CTP=SrcContainmentTreeId) self.createObxSegmentAcm(4, "68482^MDC_ATTR_ALARM_STATE^MDC", AlertState, CTP=SrcContainmentTreeId) self.createObxSegmentAcm(5, "68483^MDC_ATTR_ALARM_INACTIVATION_STATE^MDC", AlertInactivationState, CTP=SrcContainmentTreeId) self.createObxSegmentAcm(6, "68484^MDC_ATTR_ALARM_PRIORITY^MDC", AlertKindPrioStr, CTP=SrcContainmentTreeId) self.createObxSegmentAcm(7, "68485^MDC_ATTR_ALERT_TYPE^MDC", AlertKind, CTP=SrcContainmentTreeId) def addWatchdogObxSegment(self, timeoutPeriod, timeoutUnit="264320^MDC_DIM_SEC^MDC", MdsTree="1.0.0"): self.createObxSegmentAcm(8, "67860^MDC_ATTR_CONFIRM_TIMEOUT^MDC", ObsValue=timeoutPeriod, ObsUnit=timeoutUnit, ObsValueType="NM", CTP=MdsTree) def createMshSegmentAcm(self, messageTimeStr, SendingFacility, ReceivingApplication, ProcessingId): MsgControlIdVal = str(self._myMsgControlIdIter) self._myMsgControlIdIter += 1 self._ORU_R40.msh.children.get( "MSH_3").value = ActorEui64 # Sending Application self._ORU_R40.msh.children.get( "MSH_4").value = SendingFacility # Sending Facility if (ReceivingApplication is not None): self._ORU_R40.msh.children.get( "MSH_5").value = ReceivingApplication # Receiving Application self._ORU_R40.msh.children.get( "MSH_7").value = messageTimeStr # Date/Time Of Message self._ORU_R40.msh.children.get( "MSH_9").value = "ORU^R40^ORU_R40" # Message Type self._ORU_R40.msh.children.get( "MSH_10").value = MsgControlIdVal # Message Control ID self._ORU_R40.msh.children.get( "MSH_11").value = ProcessingId # Processing ID self._ORU_R40.msh.children.get( "MSH_15").value = AcceptAckTypeAcm # Accept Acknowledgment Type self._ORU_R40.msh.children.get( "MSH_16" ).value = ApplicationAckType # Application Acknowledgment Type self._ORU_R40.msh.children.get( "MSH_21" ).value = "IHE_PCD_ACM_001^IHE PCD^1.3.6.1.4.1.19376.1.6.1.4.1^ISO" # IHE_PCD_ACM_001^IHE PCD^1.3.6.1.4.1.19376.1.6.4.4^ISO def createPidSegmentAcm(self, PatientIdList, PatientName, PatientDoB, PatientSex): pid = self._ORU_R40.add_segment("PID") pid.children.get( "PID_3").value = PatientIdList # Patient Identifier List pid.children.get("PID_5").value = PatientName # Patient Name pid.children.get("PID_7").value = PatientDoB pid.children.get("PID_8").value = PatientSex def createPv1SegmentAcm(self, AssignedPatientLocation): # PV1|||CU1^^9042^HOSP1 pv1 = self._ORU_R40.add_segment("PV1") pv1.children.get("PV1_2").value = "I" pv1.children.get( "PV1_3" ).value = AssignedPatientLocation # Assigned Patient Location def incAlertCounter(self): obr = self._ORU_R40.children.get("OBR") oldCountStr = obr.children.get("OBR_3").value.split('^') oldCount = int(oldCountStr[0]) FillerOrderNumber = str( oldCount + 1) + "^" + oldCountStr[1] + "^" + oldCountStr[2] obr.children.get( "OBR_3").value = FillerOrderNumber # Filler Order Number self._ORU_R40.children.get("OBX")[2].children.get( "OBX_5").value = "continue" def setControlId(self, id): self._ORU_R40.msh.children.get("MSH_10").value = id def setAlarmTypeAndText(self, alarmType, alarmText): seg1 = self._getObxSegment(1) seg1.children.get("OBX_3").value = alarmType seg1.children.get("OBX_5").value = alarmText def setAlarmValue(self, value, obsType, unit, time): seg2 = self._getObxSegment(2) seg2.children.get("OBX_6").value = unit seg2.children.get("OBX_2").value = obsType seg2.children.get("OBX_5").value = str(value) seg2.children.get("OBX_14").value = time def setAlarmCTP(self, CTP): self._CTP = CTP def setAlarmId(self, alarmId): obr = self._ORU_R40.children.get("OBR") obr.children.get("OBR_1").value = "1" old = obr.children.get("OBR_3").value.split('^') # Set ID - OBR FillerOrderNumber = str(old[0]) + "^" + alarmId + "^" + old[2] parentAlert = "^0&" + alarmId + "&" + old[2] obr.children.get( "OBR_3").value = FillerOrderNumber # Filler Order Number def setAlarmPhase(self, AlertPhase): seg = self._getObxSegment(3) seg.children.get("OBX_5").value = AlertPhase def setAlarmState(self, AlertState): seg = self._getObxSegment(4) seg.children.get("OBX_5").value = AlertState def setAlarmInactivationState(self, AlertState): seg = self._getObxSegment(5) seg.children.get("OBX_5").value = AlertState def setAlarmPrio(self, AlertPrio): seg = self._getObxSegment(6) seg.children.get("OBX_5").value = AlertPrio def setAlarmKind(self, AlertKind): seg = self._getObxSegment(7) seg.children.get("OBX_5").value = AlertKind def getDeviceId(self): return self._ORU_R40.children.get("OBX").children.get("OBX_18").value def getLocation(self): pv1 = self._ORU_R40.children.get("PV1") return pv1.children.get("PV1_3").value def getEquip(self): seg = self._ORU_R40.children.get("OBX") return seg.children.get("OBX_18").value def getPatientId(self): pid = self._ORU_R40.children.get("PID") return pid.children.get("PID_3").value def getPatientName(self): pid = self._ORU_R40.children.get("PID") return pid.children.get("PID_5").value def getPatientDoB(self): pid = self._ORU_R40.children.get("PID") return pid.children.get("PID_7").value def getPatientSex(self): pid = self._ORU_R40.children.get("PID") return pid.children.get("PID_8").value def _getObxSegment(self, nr): # iterate over obx segments obx = self._ORU_R40.children.get("OBX") retVal = None for oneObx in obx: if oneObx.children.get("OBX_1").value == str(nr): retVal = oneObx return retVal def createObrSegmentAcm(self, messageTimeStr, UniqueAlertUuid, AlertUpdate): obr = self._ORU_R40.add_segment("OBR") obr.children.get("OBR_1").value = "1" # Set ID - OBR FillerOrderNumber = str( AlertUpdate) + "^" + UniqueAlertUuid + "^" + ActorEui64 parentAlert = "^0&" + UniqueAlertUuid + "&" + ActorEui64Sub obr.children.get( "OBR_3").value = FillerOrderNumber # Filler Order Number obr.children.get( "OBR_4" ).value = "196616^MDC_EVT_ALARM^MDC" # Universal Service Identifier obr.children.get( "OBR_7").value = messageTimeStr # Observation Date/Time # if (AlertUpdate > 0): obr.children.get("OBR_29").value = parentAlert # Parent def createObxSegmentAcm(self, Set_ID, ObsId, ObsValue=None, ObsUnit=None, ObsTimeStr=None, ObsSite=None, ObsValueType="ST", CTP="x.x.x"): obx = self._ORU_R40.add_segment("OBX") self._obxCount += 1 obx.children.get("OBX_1").value = str(self._obxCount) # Set ID if ObsValueType != "": obx.children.get("OBX_2").value = ObsValueType obx.children.get("OBX_11").value = "F" # Observation Result Status else: obx.children.get("OBX_11").value = "X" obx.children.get("OBX_3").value = ObsId # Observation Identifier obx.children.get("OBX_4").value = CTP + "." + str( Set_ID) # Observation Sub-ID if ObsValue: obx.children.get("OBX_5").value = str( ObsValue) # Observation Value if ObsUnit is not None: obx.children.get("OBX_6").value = ObsUnit # Units if (ObsTimeStr is not None): obx.children.get( "OBX_14").value = ObsTimeStr # Date/Time of the Observation obx.children.get( "OBX_18").value = self._EquipII # Equipment Instance Identifier if (ObsSite is not None): obx.children.get("OBX_20").value = ObsSite # Observation Site
def test_add_known_segment_to_empty_message(self): a = Message('OML_O33') a.add(Segment('MSA'))
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" corId = m.msh.children.get("MSH_10").value answer.msa.children.get("MSA_2").value = corId else: # answer with pcd-05 message print("************ Got Alarm {} ************".format( alarmTypeTxt)) print("Full message {}: \n{}".format( datetime.now(), pretty(m)))
def parse_message(message, validation_level=None, find_groups=True, message_profile=None, report_file=None, force_validation=False): """ Parse the given ER7-encoded message and return an instance of :class:`Message <hl7apy.core.Message>`. :type message: ``str`` :param message: the ER7-encoded message to be parsed :type validation_level: ``int`` :param validation_level: the validation level. Possible values are those defined in :class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`) :type find_groups: ``bool`` :param find_groups: if ``True``, automatically assign the segments found to the appropriate :class:`Groups <hl7apy.core.Group>` instances. If ``False``, the segments found are assigned as children of the :class:`Message <hl7apy.core.Message>` instance :type force_validation: ``bool`` :type force_validation: if ``True``, automatically forces the message validation after the end of the parsing :return: an instance of :class:`Message <hl7apy.core.Message>` >>> message = "MSH|^~\&|GHH_ADT||||20080115153000||OML^O33^OML_O33|0123456789|P|2.5||||AL\\rPID|1||" \ "566-554-3423^^^GHH^MR||EVERYMAN^ADAM^A|||M|||2222 HOME STREET^^ANN ARBOR^MI^^USA||555-555-2004|||M\\r" >>> m = parse_message(message) >>> print(m) <Message OML_O33> >>> print(m.msh.sending_application.to_er7()) GHH_ADT >>> print(m.children) [<Segment MSH>, <Group OML_O33_PATIENT>] """ message = message.lstrip() encoding_chars, message_structure, version = get_message_info(message) validation_level = _get_validation_level(validation_level) try: reference = message_profile[message_structure] if message_profile else None except KeyError: raise MessageProfileNotFound() try: m = Message(name=message_structure, reference=reference, version=version, validation_level=validation_level, encoding_chars=encoding_chars) except InvalidName: m = Message(version=version, validation_level=validation_level, encoding_chars=encoding_chars) try: children = parse_segments(message, m.version, encoding_chars, validation_level, m.reference, find_groups) except AttributeError: # m.reference can raise i children = parse_segments(message, m.version, encoding_chars, validation_level, find_groups=False) m.children = children if force_validation: if message_profile is None: Validator.validate(m, report_file=report_file) else: Validator.validate(m, message_profile[message_structure], report_file=report_file) return m
def __init__(self): self.m = Message()
def test_add_not_allowed_segment_to_known_message(self): a = Message('OML_O33', validation_level=VALIDATION_LEVEL.STRICT) self.assertRaises(ChildNotValid, a.add, Segment('MSA')) b = Message('OML_O33') b.add(Segment('MSA'))
def test_add_known_group_to_empty_message(self): a = Message('OML_O33') a.add(Group('OML_O33_PATIENT'))
def test_add_group_to_message(self): e = Message('OML_O35') self.assertRaises(ChildNotFound, e.add_group, 'UNKNOWN_GROUP') g = e.add_group('OML_O35_PATIENT') self.assertTrue(g.is_named('OML_O35_PATIENT')) self.assertEqual(g.classname, 'Group')
class HL7_Generator: def __init__(self): self.m = Message() def generate_MSH(self): """**********MSH Segment********** List of fields utilized in this segment : Sr. No. | Field Sequence Number | Field Name 1 | 17 | Country Code 2 | 19 | Principal Language Used""" # assign values to fields in MSH Segment self.m.msh.msh_17 = country_code self.m.msh.msh_19 = principal_lang def generate_EVN(self): """ **********EVN Segment********** List of fields utilized in this segment : Sr. No. | Field Sequence Number | Field Name 1 | 1 | Event Code 2 | 6 | Event Occured """ # assign values to fields in EVN Segment self.m.evn.evn_1 = event_code self.m.evn.evn_2 = self.m.msh.msh_7 self.m.evn.evn_6 = event_reason def generate_PID(self): """ **********PID Segment********** List of fields utilized in this segment : Sr. No. | Field Sequence Number | Field Name 1 | 5 | Name (Last Name, First Name, Middle Name) 2 | 6 | Mother's Maiden Name 3 | 7 | Date of Birth 4 | 8 | Sex 5 | 12 | Country Code 6 | 13 | Contact Numbers (Contact No. 1, Contact No. 2) 7 | 16 | Marital Status 8 | 17 | Religion """ # assign values to fields in PID Segment self.m.pid.pid_5.pid_5_1 = last_name self.m.pid.pid_5.pid_5_2 = first_name self.m.pid.pid_5.pid_5_3 = middle_name self.m.pid.pid_6 = mother_name self.m.pid.pid_7 = dob self.m.pid.pid_8 = sex self.m.pid.pid_12 = country_code self.m.pid.pid_13.pid_13_1 = contact_no_1 self.m.pid.pid_13.pid_13_2 = contact_no_2 self.m.pid.pid_16 = marital_status self.m.pid.pid_17 = religion def generate_OBX(self): """ **********OBX Segment********** Generate a separate OBX Segement for each of the following observations : Sr. No. | Field Sequence Number | Field Description 1 | 1 | Observation Sequence ID 2 | 3 | Observation Identifier (Observation Sequence ID, Observation Name) 3 | 5 | Observation Value 4 | 6 | Units 4 | 14 | Observation Timestamp """ # date_time = datetime.fromtimestamp(timestamp) # d = date_time.strftime("\'%Y-%m-%d %H:%M:%S\' UTC") for each in records: for i in range(len(obx_codes)): obx = Segment('OBX') obx.obx_1 = each['record_id'] obx.obx_3 = obx_codes[i] obx.obx_5 = str(each['obx_test'][i]) obx.obx_6 = obx_units[i] obx.obx_14 = each['timestamp'] self.m.add(obx) def generate_NK1(self): self.m.nk1.nk1_1 = kin_patient_id self.m.nk1.nk1_2.nk1_2_1 = kin_last_name self.m.nk1.nk1_2.nk1_2_2 = kin_first_name self.m.nk1.nk1_2.nk1_2_3 = kin_middle_name self.m.nk1.nk1_3 = relationship self.m.nk1.nk1_4 = kin_address self.m.nk1.nk1_5 = kin_phone_no self.m.nk1.nk1_6 = kin_biz_phone_no # self.m.nk1.nk1_10 = kin_job_title # self.m.nk1.nk1_13 = kin_organization self.m.nk1.nk1_14 = kin_marital_status self.m.nk1.nk1_15 = kin_sex self.m.nk1.nk1_16 = kin_dob self.m.nk1.nk1_19 = kin_citizenship self.m.nk1.nk1_20 = kin_primary_lang self.m.nk1.nk1_25 = kin_religion self.m.nk1.nk1_26 = kin_mother_name self.m.nk1.nk1_27 = country_code self.m.nk1.nk1_34 = kin_job_status self.m.nk1.nk1_37 = kin_aadhaar_no def generate_DG1(self): self.m.dg1.dg1_1 = case_id self.m.dg1.dg1_2 = 'ICD' self.m.dg1.dg1_3 = danger_code self.m.dg1.dg1_16 = practitioner_id def to_hl7(self): # f = open('er7.txt','w') self.generate_MSH() self.generate_EVN() self.generate_PID() self.generate_OBX() self.generate_NK1() self.generate_DG1() for child in self.m.children: # f.write(child.to_er7() + '\n') print(child.to_er7())
def test_create_insensitive(self): e = Message('oml_o35') self.assertEqual(e.classname, 'Message') self.assertTrue(e.is_named('OML_O35'))
def test_add_empty_children_to_message(self): a = Message('OML_O33', validation_level=VALIDATION_LEVEL.STRICT) self.assertRaises(ChildNotValid, a.add, Group()) b = Message('OML_O33') b.add(Group())
def parse_message(message, validation_level=None, find_groups=True, message_profile=None, report_file=None, force_validation=False): """ Parse the given ER7-encoded message and return an instance of :class:`Message <hl7apy.core.Message>`. :type message: ``str`` :param message: the ER7-encoded message to be parsed :type validation_level: ``int`` :param validation_level: the validation level. Possible values are those defined in :class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`) :type find_groups: ``bool`` :param find_groups: if ``True``, automatically assign the segments found to the appropriate :class:`Groups <hl7apy.core.Group>` instances. If ``False``, the segments found are assigned as children of the :class:`Message <hl7apy.core.Message>` instance :type force_validation: ``bool`` :type force_validation: if ``True``, automatically forces the message validation after the end of the parsing :return: an instance of :class:`Message <hl7apy.core.Message>` >>> message = "MSH|^~\&|GHH_ADT||||20080115153000||OML^O33^OML_O33|0123456789|P|2.5||||AL\\rPID|1||" \ "566-554-3423^^^GHH^MR||EVERYMAN^ADAM^A|||M|||2222 HOME STREET^^ANN ARBOR^MI^^USA||555-555-2004|||M\\r" >>> m = parse_message(message) >>> print(m) <Message OML_O33> >>> print(m.msh.sending_application.to_er7()) GHH_ADT >>> print(m.children) [<Segment MSH>, <Group OML_O33_PATIENT>] """ message = message.lstrip() encoding_chars, message_structure, version = get_message_info(message) validation_level = _get_validation_level(validation_level) try: reference = message_profile[message_structure] if message_profile else None except KeyError: raise MessageProfileNotFound() try: m = Message(name=message_structure, reference=reference, version=version, validation_level=validation_level, encoding_chars=encoding_chars) except InvalidName: m = Message(version=version, validation_level=validation_level, encoding_chars=encoding_chars) children = parse_segments(message, m.version, encoding_chars, validation_level, m.structure_by_name) if m.name is not None and find_groups: m.children = [] create_groups(m, children, validation_level) else: m.children = children if force_validation: if message_profile is None: Validator.validate(m, report_file=report_file) else: Validator.validate(m, message_profile[message_structure], report_file=report_file) return m