Hi Emilien. we will try to clarify some issues. Probably we didn't explain well how we would like to implement the module. I think that it is very similar to the process you are describing for incoming messages: it is a process that listens for MLLP connections from clients and returns an HL7 message as an answer. Currently it accepts only PDQ messages, but it can be easily extended to accept other kinds of messages. In this way you can have just one entry point for all HL7 transactions. Regarding the database access, we agree to implement an interface which can be reused by other transactions and hides the method for querying the database. The implementation, will use Tryton/GNUHealth methods. I think the difference from your vision is that we take configurations parameters from the Tryton configuration files while you think it is best to create a Tryton module to configure it via GUI and that can be a good solution indeed. This scenario is different from Mirth, since you'll have a native module in your HIS and you won't need to install another middleware to support interoparibility with external systems. Mirth is a terrific tool when you have to integrate systems which speak different languages; if you implement a native interface you can avoid another level of complexity. Regarding the 3 types of interface you described, actually HL7 v2 transactions require always a response with an ACK. If the sender does not receive it in a predefined period of time it will retransmit the message. As you said, in case of QRY messages (for example PDQ requests messages) the ACK will encapsulate also the results of the query within the response. So we think the interfaces are always bidirectional. That said we agree with you about the two processes: - One for incoming messages: this process gets the messages from an external system and responds with the ACK message, but it doesn't answer AA for messages with errors, since this behavior isn't compliant with HL7 specification. This process is the one we're trying to implement - One for outgoing messages: this creates the messages, send them to the external system then wait for the ACK from it. If an error happened, so the answer is AE (Applicaiton Error) or AR (Application Reject), it should implement a retransmission mechanism. If you agree, we'd like to implement a first version of incoming messages process where the Tryton module for now implements the basic parameters (e.g listening host and port) which can be extended in the future with others.
Let us know your thoughts, Vittorio 2014-09-11 22:27 GMT+02:00 Emilien Klein <[email protected]>: > Hi Vittorio, > > I'm responding directly to the health-dev mailing list, to make sure > that anyone interested in this topic (hi Andrew!) can jump in. > > 2014-09-11 16:56 GMT+02:00 Vittorio Meloni <[email protected]>: > > Thank you Louis and hello Chris and Emilien. > > I introduce my colleague Alessandro which is one of the main developer of > > the module. > > Hi Alessandro, > > > I had the pleasure to "meet" Emilien via email, when I first introduced > our > > hl7 python API to the mailing list and I also saw his thorough > presentation > > of HL7 and python-hl7 library. > > As Luis told you, we're implementing a PDQ module for GNU Health. PDQ > > (Patient Demographics Query) is one of the most popular IHE profiles and > it > > aims to allow system to retrieve patients' demographics. > > Starting with patient demographics is indeed smart. > Although I am not yet familiar with the PDQ profile, I see that it is > pointing to amongs other chapter 3 of the HL7 v2.5 specs [0]. I have > implemented and help support "regular" HL7v2 QRY^A19 at a number of > Dutch hospitals, so that shouldn't be too different from what I'm used > to ;) > > [0] http://wiki.ihe.net/index.php?title=Patient_Demographics_Query > > Another very similar message type is the ADT outgoing interface (the > response on the query is basically the same as an A08 update message), > it should be pretty easy to support that as well. > > > We're implementing it to be extensible to other IHE or HL7 transactions > in > > the future. This module will be a separated process from Tryton and it's > > based on SocketServer. > > As I wrote in the previous email, we're trying to keep the > implementation as > > integrated as possible to Tryton , so we're keeping the configuration of > the > > module integrated with the same configuration method and files of Tryton > > itself adding some legal options to the configuration file. > > Let me know your thoughts. > > I'm responding further down, after your description of the way you > plan to implement this. > At the end, I will be sharing my ideal vision for such a module. > > > Luis, I haven't understood what you mean with "parent directory": do you > > mean at the same level as tryton and misc or as child of tryton > directory? > > > > Best, > > Vittorio > > > > > > 2014-09-11 12:13 GMT+02:00 Luis Falcon <[email protected]>: > >> > >> Dear Vittorio > >> > >> Let me introduce you to Chris Zimmerman and Emilien Klein. Chris is > >> working on the implementation of both the server and the client for > >> HL7 FHIR. Emilien is a long time supporter of integrating HL7 in GNU > >> Health. He has done a cool video / presentation on HL7 plans for GNU > >> Health. > >> > >> Vittorio and his team are focusing on HL7 PDQ - correct me if I'm > >> wrong. > >> > >> I think is great you three know each other and share ideas and work. > >> > >> As far as the directory structure in Savannah, I think the best is to > >> create a parent directory called "HL7" and from there put all the > >> related projects . > >> > >> Let me know your thoughts. > >> > >> Best, > >> > >> > >> > >> On Tue, 9 Sep 2014 17:01:34 +0200 > >> Vittorio Meloni <[email protected]> wrote: > >> > >> > Thank you very much, Luis. > >> > I'll try to explain how we're implementing the module and especially > >> > how we're integrating it in GNU Health, so that you can tell me if > >> > you think it's a correct way to proceed, then I will insert a ticket > >> > in Savannah. Since, of course, we cannot access the tryton > >> > executable, we developed the hl7 server as an external process which > >> > accepts the MLLP request on a different port. > > In my opinion, this is not an optimal design. I would like to see this > "interface" module (naming it broadly, to support potentially more > than just HL7) as an integral Tryton module. > > >> > This executable is configurable using some parameters added to the > >> > tryton configuration file, for example listening host and port. The > >> > idea is that when a user wants to customize the parameters he/she can > >> > insert them in the tryton configuration file. > >> > About the query in the database, we used the python-sql module since > >> > we found in the GNU Health source some examples using it. > > Using an external executable that queries the database directly > instead of going through Tryton/GNU Health doesn't seem optimal to me. > Using this approach is basically not different than what I understood > from Luis [1] is currently done at organizations that want to exchange > HL7 data: use Mirth as an interface engine, as it has the ability to > perform SQL queries and format the result into HL7. You would > basically be re-programming in an external application what others > have already implemented in Mirth. In that case, it would make more > sense to consolidate Mirth configurations, so that it can be shared > between organizations. > > [1] http://lists.gnu.org/archive/html/health-dev/2012-11/msg00026.html > > Also, by querying the database directly, you would have to closely > keep track of the database structure, and risk breaking the interface > if a change is made to the data model. Doing that in an external > binary is less robust that if you have a well defined API to access > the database. > > >> > If you think it's ok we can continue implementing this way. > >> > Then we think that we need to put our library in the dependencies, so > >> > during the installation process it should install it from PyPi. > >> > Finally just a quick question: since it is not a classic Tryton module > >> > we're implementing, where do you think it should be put in the source > >> > tree? We're thinking to put it with the other modules anyway (e.g > >> > health/tryton/health_hl7). > >> > > >> > Hope it's ok, > >> > thank you and best. > >> > > >> > Vittorio > > So, now that I've told you that I don't share your vision (sorry about > that ;)), let me share my ideal vision with you. > > This applies regardless of the standard used to exchange information > (HL7 v2, HL7 v3, HL7 FHIR, others), but I'll use HL7v2 examples, as > that is the most frequently used standard *within* hospitals (I'm > seeing mostly HL7 v2.4). I see basically 3 types of interfaces: > > - Outgoing interfaces: > Something happens in GNU Health (let's call that a trigger) that > needs to be communicated with downstream systems. Example include > (assuming that GNU Health is the source of truth for patient > demographics and ADT [Admission/Discharge/Transfer] information, and > the order placer system): > * new patient is created (generates an HL7 ADT A04 or A28 message) > * patient's address changed (generates an HL7 ADT A08 [update] message) > * patient is admitted to the hospital (generates an HL7 ADT A01 > message) > * orders (lab, radiology, medication, etc.) are placed for a > patient (generates an HL7 ORM message [RDE for medication]) > - Incoming interfaces (assuming demographics information is kept in > another system, and the laboratory sends result messages to GNU > Health): > * new patient is created (receive an HL7 ADT A04 or A28 message) > * patient's address changed (receive an HL7 ADT A08 [update] message) > * patient is admitted to the hospital (receive an HL7 ADT A01 message) > * results are made available for a patient (receive an HL7 ORU message) > - Bidirectional interfaces (again assuming GNU Health is the source of > truth for patient demographics): > * an external system queries GNU Health for patient demographics, > and the response to that query is sent in the acknowledgment ACK > message (all messages in HL7 are replied to by an ACK message, but in > case of a query the ACK contains a payload next to the technical > acknowledgement of reception of the message) > > Disclaimer: what follows is rather similar to the interface framework > used at my day job, but my intent is not to describe that. Rather, > it's based on the best practices I have learned over the years, > working with a diverse range of systems: lab, pharmacy, radiology, > nuclear medicine med preparation, scheduling, specialty [ECG, > ophthalmology], vitals measuring devices, document management systems. > All these systems have variations around the same following concepts: > > I imagine a Tryton module (at the same level as all other GNU Health > modules) that would perform a number of tasks: > - Allow for configuration of the interfaces, i.e. configuration > parameters that allow per-interface customization (e.g. one > organization wants to send the social security number of the patient > in PID-19, while the other doesn't want that information sent out) and > - IP adress/port configuration > - Allow to indicate which events should generate messages, and which > shouldn't (don't send temporary patient moves at this organization, > but do send them at that other) > - Allow to start/stop message, send email messages if interfaces are > unexpectedly stopped, or if messages haven't been received in a > specified amount of time (you'd obviously want to set that up only on > large-volume interfaces) > - Process messages in 2 distinct stages: > * One process takes care of sending (for outgoing) or receiving > (for incoming) the actual HL7 message. This process also handles the > ACK message: for outgoing messages, if the ACK didn't contain the code > AA (Application Accept), log an error that can be reviewed later. For > incoming messages, send an ACK message to indicate that the message > was properly received (just always send AA, even if the message > couldn't be processed later. we'll handle errors separately). > Processed messages get saved in the database, for later review or > search. > * One process handles the interpretation of the message: building > the outgoing message from the database content, based on which event > was triggered, or filing the information received in the incoming > message to the database. > > This is how the 2-stage processing would work: > * For outgoing interfaces, each time a trigger is hit, keep it in > a queue for later processing (useful if the interface has to be shut > down temporarily). Then another process goes through this list of > events one by one, and creates an HL7 message corresponding to the > event, before finally removing the event from the queue. The data is > retrieved from the database, but through an abstraction layer (e.g. a > getPatientName() function, instead of directly a SELECT statement). > * For incoming interfaces, receive the HL7 message and put it on a > queue (useful if you need to temporarily stop processing incoming > messages, > * For bidirectional interfaces, there wouldn't really be 2 stages, > as these are real-time interfaces. The process receiving the query is > also responsible to send the If it's down, you don't get a response, > so you'll need to send your query again. > The reason for 2-stage processing is that it separates processing of > the message content and the communication with external parties, which > allows to adequately process temporary spikes. You wouldn't want to > drop e.g. incoming results messages, just because you're still > processing the previous message. > > A translation mechanism must be provided, which allow to send values > in the messages that might be different that the values used in GNU > Health itself. For example a lab procedure for Kalium would have the > code K in GNU Health, but KAL in the performing lab system. The > external code could be a property of the procedure itself (saved in > the database directly), but a > quick-and-dirty-but-sometimes-harder-to-maintain-and-keep-in-sync > manner to do these mappings is a simple 2-column table. > > Of course, errors can happen. e.g. an incoming message comes in with a > patient ID that is unknown, or for a lab procedure code that isn't > recognized. Or an outgoing message must be generated, but some needed > information isn't there (e.g. code of a department, or lab procedure). > We'll need an error database, that would log the situation and link > the error to the received message. > > The interface module would allow to search for messages based on > configurable parameters (e.g. show me all messages for this patient on > that interface for period X, or all lab orders for procedure Y), and > make it possible to manually edit, reprocess (incoming) or regenerate > (outgoing) messages. This is useful when a message couldn't be > processed (e.g. incorrect patient ID), the cause for the issue has > been fixed, and the message can now be processed correctly. > > This is a golden opportunity to implement the base of the system in a > way that will make developing new interfaces easily in the future, > independant of the actual communications standard used. Otherwise, > we'll get inconsistency: an HL7 FHIR module here, an IHE PDQ > executable there, direct database-reading by Mirth for these other > places. And the day that somebody wants to receive appointment > information, we'll have to think about yet another way of doing things > ;) > > I'm interested in what your thoughts are. > +Emilien >
