crs4 / hl7apy

Python library to parse, create and handle HL7 v2 messages.
http://crs4.github.io/hl7apy/
MIT License
231 stars 91 forks source link

ACK Message not Parsing Invalid Segment #139

Open jungwire opened 14 hours ago

jungwire commented 14 hours ago

Hi, everyone

I have a problem during parsing of the ACK message. May code looks like this:

            sock.sendall(message_bytes)
            response_bytes = sock.recv(4096)
            response_str = response_bytes.decode('utf-8')
            response_message = parse_message(response_str)

and my test ACK message like this: '\x0bMSH|^~\\&|SA|SF|RA|RF|20241126151031||ACK^O21|12345|T|2.5\rMSA|AA|12345\r\x1c\r'

However, I get the following Invalid name for Segment: Error:

Traceback (most recent call last):
  File "/snap/pycharm-professional/429/plugins/python/helpers-pro/pydevd_asyncio/pydevd_asyncio_utils.py", line 117, in _exec_async_code
    result = func()
  File "<input>", line 1, in <module>
  File "<PWD>/.venv/lib/python3.10/site-packages/hl7apy/parser.py", line 90, in parse_message
    children = parse_segments(message, m.version, encoding_chars, validation_level, find_groups=False)
  File "<PWD>/.venv/lib/python3.10/site-packages/hl7apy/parser.py", line 152, in parse_segments
    segment = parse_segment(s.strip(), version, encoding_chars, validation_level)
  File "<PWD>/.venv/lib/python3.10/site-packages/hl7apy/parser.py", line 238, in parse_segment
    segment = Segment(segment_name, version=version, validation_level=validation_level,
  File "<PWD>/.venv/lib/python3.10/site-packages/hl7apy/core.py", line 1612, in __init__
    super(Segment, self).__init__(name, parent, reference, version,
  File "<PWD>/.venv/lib/python3.10/site-packages/hl7apy/core.py", line 642, in __init__
    self._find_structure(reference)
  File "<PWD>/.venv/lib/python3.10/site-packages/hl7apy/core.py", line 819, in _find_structure
    structure = ElementFinder.get_structure(self, reference)
  File "<PWD>/.venv/lib/python3.10/site-packages/hl7apy/core.py", line 552, in get_structure
    raise InvalidName(element.classname, element.name)
hl7apy.exceptions.InvalidName: Invalid name for Segment: 

After trying some things I figured out that removing the End of Block \x1c\r of the framing allows for correct parsing. But this seem like a work around.

            clean_response = response_str.strip('\x0b\x1c\r')
            response_message = parse_message(clean_response)

Any help is much appreciated

svituz commented 13 hours ago

Those characters are part of the MLLP message, the protocol defined by HL7 to send messages. MLLP is a very simple protocol that encloses the message between the bytes \x0b{HL7_MESSAGE}\x1c\r, so when you receive the message from the network with the protocol, you do need to extract it, getting rid of the bytes.

svituz commented 13 hours ago

BTW, if you're implementing an HL7 server, you can try the MLLPServer class which takes care of receiving and extracting the message from MLLP serialization. You can see how it works in the examples directory