Blog
HL7 FHIR, pronounced "fire", is a data model and message transfer protocol designed to facilitate the exchange of information among systems used in health care settings.
In such environments, a FHIR server will assume the role of a central repository of health records with other systems integrating with it, potentially in a hub-and-spoke fashion, thus letting the FHIR server become a unified and consistent source of data that would otherwise stay confined to a silo of each individual health information system.
While FHIR is the way forward, the current reality of health care systems is that much of the useful and actionable information is distributed and scattered among many individual data sources - paper-based directories, applications or data bases belonging to the same or different enterprises - and that directly hampers the progress towards delivering good health care. Anyone witnessing health providers copy-and-pasting the same information from one application to another, not having access to the already existing data, not to mention people not having an easy way to access their own data about themselves either, can understand what the lack of interoperability looks like externally.
The challenges that integrators face are two-fold. On the one hand, the already existing systems, including software as well as medical appliances, were often not, or are still not being, designed for the contemporary inter-connected world. On the other hand, FHIR in itself is a relatively new technology which means that it is not straightforward to re-use the existing skills and competencies.
Zato is an open-source platform that makes it possible to integrate systems with FHIR using Python. Specifically, its support for FHIR enables quick on-boarding of integrators who may be new to health care interoperability, who are coming to FHIR with previous experience or interest in web development technologies, and who need an easy way to get started with and to navigate the complex landscape of health care integrations.
Outgoing FHIR connections are what allows Python-based services to communicate with FHIR servers. Throughout the rest of the chapter, the following definition will be used. It connects to a live, publicly available FHIR server.
Filling out the form below will suffice, there is no need for any server restarts. This principle, that restarts are not needed, applies all throughout the platform, whenever you change any piece of configuration, it will be automatically propagated as necessary.
In Python code, you obtain client connections to FHIR servers through self.out.hl7.fhir objects, as in the example below which first refers to the server by its name and then looks up all the patients in the server.
The structure of the Patient resource that we expect to receive can be found here.
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class FHIService1(Service):
name = 'demo.fhir.1'
def handle(self) -> 'None':
# Connection to use
conn_name = 'FHIR.Sample'
with self.out.hl7.fhir[conn_name].conn.client() as client:
# This is how we can refer to patients
patients = client.resources('Patient')
# Get all active patients, sorted by their birth date
result = patients.sort('active', '-birthdate')
# Log the result that we received
for elem in result:
self.logger.info('Received -> %s', elem['name'])
Invoking the service will store in logs the data expected:
For comparison, this is what the FHIR server displays in its frontend. - the information is the same.
To save information in a FHIR server, create the required resources and call .save to permanently store the data in the server. Resources can be saved either individually (as in the example below) or as a bundle.
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class CommandsService(Service):
name = 'demo.fhir.2'
def handle(self) -> 'None':
# Connection to use
conn_name = 'FHIR.Sample'
with self.out.hl7.fhir[conn_name].conn.client() as client:
# First, create a new patient
patient = client.resource('Patient')
# Save the patient in the FHIR server
patient.save()
# Create a new appointment object
appointment = client.resource('Appointment')
# Who will attend it
participant = {
'actor': patient,
'status':'accepted'
}
# Fill out the information about the appointment
appointment.status = 'booked'
appointment.participant = [participant]
appointment.start = '2022-11-11T11:11:11.111+00:00'
appointment.end = '2022-12-22T22:22:22.222+00:00'
# Save the appointment in the FHIR server
appointment.save()
The "R" in FHIR stands for "Resources" and the sample code above uses resources such a Patient or Appointment but how does one learn what other resources exist and what they look like? In other words, how does one learn the underlying data model?
First, you need to get familiar with the spec itself which, in addition to textual information, offers visualizations of the data model. For instance, here is the description of the Observation object, including details such as all the attributes an Observation is composed of as well as their multiplicities.
Secondly, do spend time with FHIR servers such as Simplifier. Use Zato services to create test resources, look them up and compare the results with what the spec says. There is no substitute for experimentation when learning a new data model.
Outgoing FHIR connections can be secured in several ways, depending on what a given FHIR requires:
While FHIR is what new deployments use, it is worth to add that there are still other HL7 versions frequently seen in integrations:
Both of them can be used in Zato services, in both directions. For instance, it is possible to both receive HL7 v2 messages as well as to send them to external applications. It is also possible to send v2 messages using REST in addition to MLLP.