integration administrator guide
TRANSCRIPT
-
8/4/2019 Integration Administrator Guide
1/16
PatientOS
PatientOSIntegration
Administrator Guide
Version 1.0
-
8/4/2019 Integration Administrator Guide
2/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 1 of 16
Revision HistoryDate Version Description Author
04/17/2008 1.0 Initial for version 0.70 Greg Caulton
-
8/4/2019 Integration Administrator Guide
3/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 2 of 16
Contents1. OVERVIEW........................................................................................................................................................................
1.1 DEFAULT SETTINGS ............................................................................................ ERROR!BOOKMARK NOT DEFINE1.2 DEFINITIONS ................................................................................................................................................................. 2. SYSTEM SETTINGS ........................................................................................ERROR! BOOKMARK NOT DEFINED
2.1 SETTINGS TOOL .................................................................................................. ERROR!BOOKMARK NOT DEFINE2.2 CHANGING A SETTING ........................................................................................ ERROR!BOOKMARK NOT DEFINE2.3 ADDING A SETTING............................................................................................. ERROR!BOOKMARK NOT DEFINE
3. BATCH JOBS ....................................................................................................ERROR! BOOKMARK NOT DEFINED3.1 ADDING BATCH JOBS.......................................................................................... ERROR!BOOKMARK NOT DEFINE3.2 SCHEDULING BATCH JOBS.................................................................................. ERROR!BOOKMARK NOT DEFINE
4. SYSTEM IDENTIFIERS ..................................................................................ERROR! BOOKMARK NOT DEFINED4.1 IDENTIFIER SOURCE TOOL.................................................................................. ERROR!BOOKMARK NOT DEFINE4.2 ADDING AN IDENTFIER SOURCE ......................................................................... ERROR!BOOKMARK NOT DEFINE
5. PATIENT PORTAL ..........................................................................................ERROR! BOOKMARK NOT DEFINED5.1 LOGIN.................................................................................................................. ERROR!BOOKMARK NOT DEFINE
-
8/4/2019 Integration Administrator Guide
4/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 3 of 16
Integration Administrator Guide1. Overview
1.1 Integration
There are a number of inbound and outbound interfaces for PatientOS using Mirth for the majority of the integrationpoints. The list is not limited to:
a) Standard HL7 Interfaces.a. ADT Inboundb. ADT Outboundc. Lab Results Inboundd. Lab Orders Outbound
b) XML or any other format supporting by Mirtha. XML Forms/Clinical Results Inboundb. XML Clinical
c) Web developmenta. Patient Portal running within the JBoss container
d) Batch processinga. Scheduled scripts which can directly reference the EJB services
e) JDBCa. Direct SQL (not recommended except for read only access)
1.2 Definitions
POS Refers to the PatientOS software as a system.
-
8/4/2019 Integration Administrator Guide
5/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 4 of 16
2. XML Forms/Clinical Results Inbound
2.1 Overview
Mirth is an enterprise class integration engine with which PatientOS integrates. For inbound forms the basic flow is
i) Mirth receives the XML file (from filesystem, JDBC, or port, etc)ii) Mirth maps the XML content into the PatientOS XML format for Recordsiii) Mirth inserts the XML into the interface_messages tableiv) PatientOS interface controller (running as a JBoss service) picks up the filev) The appropriate Converter is called to map the XML to the PatientOS FormRecordModelvi) The model is stored writing to the records and record_details (if populated).
2.2 Mirth Setup
2.2.1 Start Mirth
To setup mirth start Mirth using Start Program Files PatientOSversion Interface Engine
Figure 1 Starting Mirth
For a production implementation Mirth would be installed as a service.
2.2.2 Start Mirth Manager
To setup the interface channels start the Mirth Manager using Start Program Files PatientOSversion Interface
Manager. Login with
admin/admin
Figure 2 admin/admin
-
8/4/2019 Integration Administrator Guide
6/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 5 of 16
2.2.3 Channels
Select the channels tab and view the existing channels (if the channels were not included download from
http://www.patientos.org/documentation. Download the file oru_xml_file_pos_db.xml. The file name indicates it is a
results file reading XML from a file and posting it into the PatientOS database.
Select the channel ORU XML File POS DB and Edit Channel to edit the properties.
Figure 3 Channels
The first tab defines that XML is being read and this channel will auto start.
Figure 4 Summary tab
-
8/4/2019 Integration Administrator Guide
7/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 6 of 16
2.2.4 XML Inbound Directory
Clicking on the Source tab will show which directory is being read to find the XML content and the file name formatrequired to process.
Note that the directory is defined as a relative path. It is relative from where the interface engine started (interfaces.bat or
interfaces.sh). On windows this path would be
C:\Program Files\PatientOS\\server\interfaces\bin
Figure 5 Source tab
In the figure above you can see that the channel will search for xml files in the directory
C:\Program Files\PatientOS\\server\interfaces\activity\oru_xml_in
every second.
-
8/4/2019 Integration Administrator Guide
8/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 7 of 16
2.2.5 Destination
On the destinations tab you can see the SQL used to insert into the PatientOS interface_messages table.
Take careful note of the URL and ensure the correct database is being accessed. In this case qapos is shown though thedefault should be demopos with the correct username and password.
Figure 6 Destination tab
Click on the Edit Transformer link to open the Transformer. Paste your XML into the top right frame and the XML elemen
will be parsed and displayed in a tree below. It helps if your XML is populated with sample data.
Figure 7 Transformer incoming
-
8/4/2019 Integration Administrator Guide
9/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 8 of 16
2.2.6 Transformer
PatientOS is setup with Javascript to map the incoming XML elements to the PatientOS XML elements.
The Outgoing tab serves to display a template XML which is populated by the Javascript. For this reason we want as little
data as possible (most is not needed).
However in order to see all the fields you might like to populate you can paste into the frame the RecordTransaction.xml file
from http://www.patientos.org/documentation
When have finished mapping replace the contents with the original XML You may need to tailor the XML (for example we
will add RecordDetailModel rows.
Figure 8 Outgoing data tab
The goal is to populate
a) Enough of the PatientModel to match the patient name and MRN (matching is a large topic) unless you have thepatient_id from the patients table.
b) A single FormModel to reflect the formc) As many RecordModel has you have fields on this virtual form.d) As many RecordDetailModel if you have details for a specific Record.
The concept of Record and RecordDetail is that the Record value is the significant value e.g. height, weight, lab results etc
where as the RecordDetail are child details e.g. Clothing the patient had on when weighed or comments on the lab result.
The script is written in Javascript and obviously you need some programming skills to understand the nuances of iterating
through the XML elements and building up the target XML which is this tmp structure.
-
8/4/2019 Integration Administrator Guide
10/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 9 of 16
2.2.7 Example Mapping
We will work with this sample XML
4
300
motion
2008-01-18T00:00:00.000+01:00
2008-01-18T00:15:00.000+01:00
89,22,0,0,0,0,0,0,0,2,22,24,4,12,99,140,120,94,2,0,0,0,4,5,32,4,0,0,0,0,0,0,0,0,0,0,32,12,1,0,
3,0,0,0,2,5,0,0,0,0,1,4,9,10,4,0,0,0,0
commaSeparatedValues and sensorType are real:)!
hammed motion
minutes
The patientId is actually the MRN and so in the javascript we first create the MRN mapping by dragging the XML patientID
over to the javascript page. If you have setup a facility other than the default you would enter the reference key (your facilit
name uppercase with spaces removed).
Figure 9 Drag patientid to be MRN
2.2.8 Records
On version 1.6 of Mith one way of creating the many iterations of RecordModel is to have the first defined in the template
and then copy it each time to add to the XML. This section of Javascript will likely change to an easier to perform this in
later version of Mirth.
But essentially we know there are 8 records needed so we loop 8 times and within the loop duplicate the first RecordModel,
map the values and where possible set common values outside each if statement. Not great but it works
-
8/4/2019 Integration Administrator Guide
11/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 10 of 16
You must setup an Identifier Source (login to PatientOS as admin/admin and select Identifier Sources) specific to where this
incoming data is coming from. PatientOS supports multiple interfaces and the source is a unique identifier for all external
identifiers.
In this example Porcupine Sensor was used as the identifier source.
Figure 10 Create identifier source
2.2.9 Javascript
Ideally all the record_items have been created in PatientOS. The display must be unique in the database in order to reduce
confusion with multiple items with the same name (it is possible to have dups but not recommended).
The short display is typically used on controls, reports etc. The display being the formal name.
The interface will add these items on the fly (writes to the record_items and record_item_details tables). Ideally preload
using a reference spreadsheet, then import the record items.
Note dates must be formatted YYYYMMDD and mapped to the date component or YYYYMMDDHHMMSS and mapped the date/time format. Rather than parsing we will hard code it to get started with testing
// map the MRN to match the patient
tmp['PatientModel']['IdentifierModel']['sourceRef']['idvalue'] = "DEFAULTFACILITY";
tmp['PatientModel']['IdentifierModel']['idvalue'] =
msg['ns1:patientId'].toString();
for (i=0; i
-
8/4/2019 Integration Administrator Guide
12/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 11 of 16
tmp['RecordModel'][i]['dataTypeRef']['id'] = 56990; // DOUBLE
tmp['RecordModel'][i]['valueDouble'] = msg['ns1:measureFrequency'].toString();
} else if (i==1) { // sensor type
tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element
tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONSENSORTYPE";
tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Sensor Type";tmp['RecordModel'][i]['dataTypeRef']['id'] = 79128; // STRING
tmp['RecordModel'][i]['valueString'] = msg['ns1:sensorType'].toString();
} else if (i==2) { // timestart
tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element
tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONTIMESTART";
tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Time Start";
tmp['RecordModel'][i]['dataTypeRef']['id'] = 56992; // DATE
tmp['RecordModel'][i]['valueDate']['datetime'] = startTime;
} else if (i==3) { // timestop
tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element
tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONTIMESTOP";
tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Time Stop";
tmp['RecordModel'][i]['dataTypeRef']['id'] = 56992; // DATE
tmp['RecordModel'][i]['valueDate']['datetime'] = stopTime;
} else if (i==4) { // commaseparatedvalues
tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element
tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONHAMMEDMOTION";
tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Hammed Motion";
tmp['RecordModel'][i]['dataTypeRef']['id'] = 79128; // STRING
tmp['RecordModel'][i]['valueString'] =
msg['ns1:commaSeparatedValues'].toString();
} else if (i==5) { // comment
tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element
tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONCOMMENT";
tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Comment";tmp['RecordModel'][i]['dataTypeRef']['id'] = 79128; // STRING
tmp['RecordModel'][i]['valueString'] = msg['ns1:comment'].toString();
} else if (i==6) { // dataunit
tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element
tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONDATAUNIT";
tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Data Unit";
tmp['RecordModel'][i]['dataTypeRef']['id'] = 79128; // STRING
tmp['RecordModel'][i]['valueString'] = msg['ns1:dataUnit'].toString();
} else if (i==7) { // intervalunit
tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element
tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONINTERVALUNIT";
tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Interval Unit";tmp['RecordModel'][i]['dataTypeRef']['id'] = 79128; // STRING
tmp['RecordModel'][i]['valueString'] = msg['ns1:intervalUnit'].toString();
}
// Common
tmp['RecordModel'][i]['recordDt']['datetime'] = startTime;
tmp['RecordModel'][i]['recordItemRef']['identifierSource'] = "PORCUPINESENSOR";
}
-
8/4/2019 Integration Administrator Guide
13/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 12 of 16
2.2.10 Deploy
Make sure the Outgoing Data script is
After saving the transformer changes the channel is deployed
Figure 11 Deploy changes
Now drop a copy of your xml file into the oru_xml_in directory identified earlier. The channel will remove the file and any
errors will be written to the log.
On the dashboard we can see an error occurred:
Figure 12 Dashboard
Selecting Events will show the log, selecting the first entry and scrolling down the exception log we find the error relates to
the ns1 prefix used in the XML
Figure 13 Event log for errors
-
8/4/2019 Integration Administrator Guide
14/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 13 of 16
After attempting some javascript tricks to remove or build the namespace the event log stopped filling with error messages.
Instead by right clicking on the channel in the dashboard you can select View Messages
You can select the message which errored and view the different states the message went through before and after the
transformating Javascript. On the error tab we see the namespace is still an issue.
Figure 14 Message view for the big picture
To resolve the issue on the Summary tab we deselected Strip namespace from messages and as show above the message
was transformed and sent i.e. written to the interface_messages table.
-
8/4/2019 Integration Administrator Guide
15/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 14 of 16
2.3 PatientOS Processing
We can find our interface message in the interface_messages table
Figure 15 Interface messages table
Logging into PatientOS as admin/admin and opening the Interface Manager shows that the ResultTransaction processing ha
already started but has not processed anything yet.
But we posted a RecordTransaction so that is why it was not picked up yet. This will be included in the next version but I
can add one (using SQL to assign the poll script). Restarting the server and this interface processor will start.
-
8/4/2019 Integration Administrator Guide
16/16
Integration Last printed 4/18/2008 1:53:00 AM
Administrator Guide Version 1.0
Page 15 of 16
2.3.1 Errors
A snippet of the error message is written to the interface_messages table (select * from interface_messages) but currently yo
need to have JBoss running in console mode so you can see the exact error.
e.g. This error shows the MRN was not passed and confirm in Mirth on the messages tab.
23:38:01,125 WARN [JDBCExceptionReporter] SQL Error: 0, SQLState: 42883
23:38:01,125 ERROR [JDBCExceptionReporter] ERROR: operator does not exist:
character varying = bytea
23:38:01,125 ERROR [Log] data.common.BaseData.sqlQuery:select p.patient_id from
identifiers i, patient_identifier pi, patients p where i.id
value = :idvalue and i.source_ref_id = :identifierSourceRefId and i.identifier_id
= pi.identifier_id and pi.patient_id = p.patient_id and
p.active_ind = 1 idvalue = null identifierSourceRefId = 1000447(sqlQuery-
query)
23:38:01,125 ERROR [Log] org.hibernate.exception.SQLGrammarException could not
execute query...
After fixing the mapping in Mirth (namespaces were causing problems again now removed from the XML) the message
gets this error in the interface_messages table:
com.patientis.model.clinical.FormModel.validateDataModel(FormModel.java:55)
JBoss showed the desired exception
00:05:38,078 ERROR [Log] com.patientis.model.clinical.NoRecordsInFormException null...
The validation failed for the FormModel due to all records being discarded likely to each each FormRecordModel being
rejected due to failed validation.
Checking the FormRecordModel the patient id is required and not populated in this version so an upgrade is required to
fix that issue.