Saturday, 3 October 2020

I'm back

Sorry about the missing me...

I'm still doing this HL7 and FHIR Integrations but have been really busy with it.  Also, I'm now using Integration Host as my Integration Engine, so don't really have the pain anymore that required this blog.  However, I know it's helped a few of your out there, so I'll try and make sure I add in some of the steps I perform.  I've updated a couple of my old posts too as Mirth Connect is now called NextGen Connect.  I still use "Connect" at a number of sites, but avoid it when possible.  HL7 Soup's much cheaper when you add in your time, it's a no brainer (heck, even Lyniate's cheaper than "Mirth" when you include your time).


Double double-quotes in HL7

Firstly, what does it mean?

PID||""|564346^^^MRN^MR

The simple answer is that the value represents blank.  But that raises the next question:  Isn't that the same as just leaving it blank?

No.  In HL7, if nothing is between the pipes it means that the value wasn't provided, or that it isn't known by the sending system.  That means that if you receive an update patient message, for example, where the patient's surname name is not provided in the PID-5.1, you should leave your records as they are. It would be wrong to update your database to nothing in this instance.

However, if you receive an "" then the sending system is telling you to update your database value to nothing, even if you have a value.  Yep, it's a way to blank out your value.

To me it feels like an awkward extension to HL7, I can picture when some tech in the early '90s pointed out this need and it got fudged into the HL7 structure.  However, it is what it is...

But then the important question is how to deal with it?

Well, now that I do my integrations in HL7 Soup's Integration Host, things have become simpler (yeah, like everything else).

Any binding between messages or variables supports a right-click option to "HL7 Encode with Quotes" that will automatically add the quotes into any value if it's omitted. Great if you're converting data in your system or another file to HL7 and want to put in the "" when it's blank to update the other system (without having to write code all the time!)

And the reverse is there too.  Say you receive an HL7 message and don't have the capacity in your web services to handle the "" value, well, you can right-click and "HL7 Decode with Quotes" and any "" value will be converted to an empty string of text.  

Even better, these functions will also handle the & and pipes that may occur to. 



Thursday, 8 November 2018

Writing Base64 encoded HL7 data to a Binary file

It is common to have Base64 encode data in an OBX-5 field. The most common I've come across are PDF documents, but also .Doc, Docx and other Document formats are common, as are the many image formats - TIFF, PNG, JPG, and BMP.

HL7 Soup is now my go-to HL7 integration engine for binary formats as it's just so simple, while at the same time it's totally flexible.  Let me show you. 

Create a receiver workflow that receives an HL7 message and then writes it out to a file.

In the transformers of the “File Writer” activity, drag the OBX-5 into the transformers list to create a new variable.


Then back in the “File Writer” change the message template to write out the variable (delete the default message template, the right click in message template and insert variable).


Now Just change the message type of the file you want to write to binary and you’ll have a binary file.


And that is it done.  Writing out a binary file automatically decodes the value from base64.  No mucking about with code or anything fiddly like that.  

OK, but what if it wasn’t actually binary data, you just had base64 encoded text for instance?  Well, you also have the option to right click on the variable and tell it to base64 decode the value like so. 




There are lots of different types of encoding available too.  Depending on the Message Type you select, you get different options.  E.g. if I had written out an XML document then right-clicking on the variable would allow me to "XML Encode" the data which replaces the &'s & etc.

Sunday, 12 August 2018

Get Patient Email Address from HL7 repeat Fields

The HL7 inbound messages I was receiving were a bit inconsistent on where to find the patient emails.  Basically, I need to look at the PID-14 and all repeating instances of this, one at a time until I find an email address.
It sounded to me like a good opportunity to try out HL7 Soups custom parameters, where I can code up my logic in c#.

Firstly I went through there introduction video on custom transformers, and then grabbed the sample code to base mine transformer on. 

I must say that I love the API, it makes coding with HL7 super easy.  The trick I found is to make sure you typecast the messages to IHL7Message right at the beginning.  It gives you heaps more methods and properties than the basic IMessage type (which is generic because it also works with JSON, CSV, etc).

The only thing I tripped up on was finding the repeat fields themselves.  I thought they may have been accessible on the GetFields() method, so I mucked around there for a bit.  But actually, they are a property of IField.  I just needed to call GetRelatedRepeatFields(), and it gave me an iterator that included the original field and its siblings.

The deployment was easy, and I loved the debugging right in Visual Studio.  So much easier than having to log out each line like in Mirth.

Anyway, here is the code I created, hope it helps.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HL7Soup.Integrations;

namespace CustomTransformersSample
{
    [Variable("Patient Email", "sample@sample.com")]
    [DisplayName("Find Patient Email")]
    public class FindPatientEmail : CustomTransformer
    {
        public override void Transform(IWorkflowInstance workflowInstance, IMessage message, Dictionary<string, string> parameters)
        {
            string email = "";
            //Get the incoming message
            IHL7Message hl7 = workflowInstance.Activities[0].Message as IHL7Message;

            //Find the PID-14
            IHL7Field pid14 = (IHL7Field)hl7.GetPart("PID-14");
            if (pid14 != null)
            {
                //Look at all the PID 14s
                foreach (var repeatField in pid14.GetRelatedRepeatFields())
                {
                    //Get the 4th component (which is email)
                    IHL7Component component = repeatField.GetComponent("4");
                    if (component != null && component.Text != "")
                    {
                        //Found the email.  Return it.
                        email = component.Text;
                        break;
                    }
                }
            }

            workflowInstance.SetVariable("Patient Email", email);
        }
    }

}

Thursday, 10 August 2017

Update HL7 Soup Example messages

When you load up HL7 Soup you are presented with a selection of example HL7 messages.  They are great to get you going, but won't necessarily be what you normally need at start-up.
You may want your own message samples, or maybe you just want a blank page.  The great thing is that you can change these by simply making your changes and clicking save.
You can add your own HL7 messages, delete the ones you don't like, or edit the defaults to your hearts content.  Just click save when you are done, and you'll be confronted with your changes when you next load HL7 Soup.

So where is this stored? Well, I did a bit of hunting and found the file is stored at

%appdata%\hl7soup\Sample HL7 Messages.txt

You can just put your own file in its place too and it will be picked up as the HL7 Soup default.

One last thing, you might want to revert to the HL7 Soup default messages again.  I found a simple workaround that recovers these.  Just delete the file I mentioned above and when you reload HL7 Soup it will add it back in with the original sample HL7 messages.  Very handy.


Thursday, 3 November 2016

Setting the Encoding in HL7 Soup

I’ve been working on an integration to an old HL7 system where all the messages are encoded with ASCII.  This was causing values like ┬Ámol/L to show as ?mol/L in HL7 Soup.  It also impacts characters like the copyright © symbol.

OK, so there was a very simple fix – I just had to upgrade to the latest version of HL7 Soup, then everything just started working.  However, in the process, I found out some new encoding features.
You can actually set the encoding that is to be used in the HL7 Soup config file.

Navigate to the HL7 Soup Config file found at
C:\Program Files (x86)\Popokey\HL7 Soup\HL7Soup.exe.config
And copy it to your desktop.

Open it up in notepad and locate the Encoding setting

<setting name="Encoding" serializeAs="String">
    <value>Default</value>
</setting>


The Default option suggests that loading or sending HL7 messages will use the default encoding on the PC, which is most likely ISO-8859-1. I think that the Default will be the best for most users, but the option is still there if you need to force a change.


To change the HL7 message encoding to ASCII
<setting name="Encoding" serializeAs="String">
    <value>ASCII</value>
</setting>



To change the HL7 message encoding to UTF-8
<setting name="Encoding" serializeAs="String">
    <value>UTF-8</value>
</setting>


To change the HL7 message encoding to ISO-8859-1
<setting name="Encoding" serializeAs="String">
    <value>UTF-8</value>
</setting>


There is also DefaultUTF-8 option that loads messages using the default encoding on the PC, but once it is sent it will just use UTF-8. I think that this will come in handy for those that have strict UTF-8 requirements for the sending, but always get sent ISO-8859-1 messages.


Once you have made your changes, save the file and copy it back to C:\Program Files (x86)\Popokey\HL7 Soup\
Overwrite the existing file with this edited version and restart HL7 Soup for the changes to take effect.














Monday, 25 July 2016

Mirth CertificateException No name matching found

I keep getting emailed questions about this error, so I thought it would be time to put the answer on the web.

Web Service Sender error
ERROR MESSAGE: Error invoking web servicecom.sun.xml.internal.ws.client.ClientTransportException: HTTP transport error: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching xxxxxxx.com found

You get this message in Mirth Connect when trying to call a web service destination. Here is the problem. Mirth seems to generate the wrong Location URI.

Here you see that I don’t have https in the address, but the Location URI has been generated with the ‘s’

clip_image001

The reverse applies sometimes too.

The work around is simple, just edit the text or the Location URI to match that of the WSDL URL (add or delete an ‘s’). The greyed out text box might make you think this is disabled, but not true – it’s just a poor UI choice.

Here is the full error message.

Web Service Sender error
ERROR MESSAGE: Error invoking web service
com.sun.xml.internal.ws.client.ClientTransportException: HTTP transport error: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching xxxxxxx.com found
                at com.sun.xml.internal.ws.transport.http.client.HttpClientTransport.getOutput(Unknown Source)
                at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.process(Unknown Source)
                at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.processRequest(Unknown Source)
                at com.sun.xml.internal.ws.transport.DeferredTransportPipe.processRequest(Unknown Source)
                at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Unknown Source)
                at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Unknown Source)
                at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Unknown Source)
                at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Unknown Source)
                at com.sun.xml.internal.ws.client.Stub.process(Unknown Source)
                at com.sun.xml.internal.ws.client.dispatch.DispatchImpl.doInvoke(Unknown Source)
                at com.sun.xml.internal.ws.client.dispatch.DispatchImpl.invoke(Unknown Source)
                at com.mirth.connect.connectors.ws.WebServiceDispatcher$DispatchTask.call(WebServiceDispatcher.java:734)
                at java.util.concurrent.FutureTask.run(Unknown Source)
                at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
                at java.lang.Thread.run(Unknown Source)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching leandrovm2008c.winscribe.com found
                at sun.security.ssl.Alerts.getSSLException(Unknown Source)
                at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
                at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
                at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
                at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
                at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
                at sun.security.ssl.Handshaker.processLoop(Unknown Source)
                at sun.security.ssl.Handshaker.process_record(Unknown Source)
                at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
                at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
                at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
                at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
                at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
                at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
                at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(Unknown Source)
                at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
                at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
                ... 16 more
Caused by: java.security.cert.CertificateException: No name matching leandrovm2008c.winscribe.com found
                at sun.security.util.HostnameChecker.matchDNS(Unknown Source)
                at sun.security.util.HostnameChecker.match(Unknown Source)
                at sun.security.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source)
                at sun.security.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source)
                at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
                at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
                ... 29 more