Ens.MessageHeader has a Status column.  You may need to select on the name or its corresponding number depending on select mode.  For example, status "Suspended" is 5.  If selecting in display mode, use Status='Suspended' and in raw mode use Status=5 in your where clause.

The number for each status is defined in macros in EnsConstants.inc - the ones that start with eMessageStatus

I was able to find APIs for the tasks being performed in Sebastian's custom code.  It is preferrable that APIs are used rather than direct global access.  I also discovered another method of finding the PatientID, rather than having to extract it from the RowID.  This code should be equivalent to Sebastian's code:

ClassMethod GetSneezinessViewerTransform(id) As %String
set patientid = %request.Data("PatientID",1)
set streamletID = ##class(web.SDA3.Loader).GetStreamletId(,patientid,"ALG",id)
set tSC = ##class(HS.SDA3.Container).LoadSDAObject(streamletID,.allergySDA3)
set sneeziness = allergySDA3.sneeziness
quit sneeziness

The reason this is happening is because your message specifies UTF-8 in MSH:18.  If you remove that from your test message, it will look correct.

When using the 'test' button to test a DTL, it will always try to use the encoding defined in MSH:18 to read the message.

When using a business service to read the message, it will try to use the encoding defined in MSH:18 if it is defined.  If it is not defined, then the 'Default Char Encoding' setting determines which encoding will be used.  You can force the 'Default Char Encoding' to override MSH:18 by putting a ! before it.


class Ens.Util.LookupTable has %Import and %Export methods.  You can use %Export to export an existing table to see the format expected by %Import.

Another option is to import a csv file using the SQL Data Import Wizard.  You can find that at System Explorer -> SQL and then click the 'Wizards' link at the top and choose Data Import.  I believe the csv file needs 3 columns: tablename, key, value.  The table name gets repeated for every row.  I'm not sure if this can be automated.

The last option is to edit the globals directly.  Ens.Util.LookupTable doesn't use standard default storage.  Instead, everything is stored in ^Ens.LookupTable with this format:


The last two options break the abstraction barrier so if the way lookup tables are stored ever changes, they'll stop working.  %Import and %Export are preferred.

I just tested this in latest and it worked fine for me.  Here is the Message Structure Raw Definition I used:


Here is a screenshot showing the visual representation of the Message Structure:

I created a sample message by modifying a sample ORU_R01 I had and I opened it in the Interoperate message viewer using these settings (my Schema is named CommunityTest and my DocType is named TEST):

When I view the file and mouse over the final NTE segment, here is the VDoc path I'm given.  You can see that it's in the OBXgrp:

What version are you on?  I think you should open a WRC problem to investigate this further.  You can call the WRC at 617-621-0700 or you can email support@intersystems.com

Why does saving the content of the PID segment in a SQL table require you to convert it to JSON or XML?  What format does it need to be in in the SQL table?

You can extract the entire PID segment with something like source.GetValueAt("PID") depending on your DocType structure.  If you just need to wrap it in XML tags then set xml = "<PID>"_source.GetValueAt("PID")_"</PID>".

There's no SFT in your DocType structure.  Your ORCgrp has optional/repeatable NTE, and your OBXgrp has optional/repeatable OBX and NTE.  Your ORCgrp also requires there to be a TQS segment before the start of OBXgrp.

Without a TQS segment, any NTEs after an OBR will be part of ORCgrp.  In other words, all NTEs after an OBR but before a TQS are part of the ORCgrp, not the OBXgrp.

If you expect that the TQS segment can be missing before the start of the OBXgrp then it needs to be optional.  The SFT segment also needs to be accounted for, either in the ORCgrp or the OBXgrp.

It's probably a good idea to contact your sales engineers for assistance designing your custom schema, or to open a WRC problem to investigate this further.

On top of that, for the field portion of the VDoc path, using a numeric reference will always work, even if the segment structure of the message doesn't match the schema.

In order to see how to reference the field by name rather than numeric, the best tool to use is the Interoperate message viewer.  This can be found in the management portal at Ensemble->Interoperate->HL7 v2.x->HL7 Message Viewer.

If you save your message as a file and open it using this message viewer, and set the DocType correctly, then you will see the message on the right side with all segment identifiers and fields highlighted in blue.  You can mouse over any segment identifier to see the exact segment path needed to reach that segment, and then you can mouse over any field to see the name that should be used to reference that field.

Here are some examples.  First is the settings I used to open the message, followed by the tooltip when I mouse over the OBX segment, followed by the tooltip when I mouse over the '39' field.

In general, you should not leave any parentheses in the segment portion of a VDoc path empty.  If your DTL references target.{PIDgrpgrp().ORCgrp().OBXgrp(1).OBX:5.2}, how will the DTL know which PIDgrpgrp or which ORCgrp you're trying to reference?

If you can guarantee your messages will only have one PIDgrpgrp and one ORCgrp within that, then you can just use 1's, like this: target.{PIDgrpgrp(1).ORCgrp(1).OBXgrp(1).OBX:5.2}

If it's possible your messages will have multiple PIDgrpgrps or ORCgrps, then you may need nested foreach loops to reach all of them.  Even in the foreach loop, only the last set of parentheses in the segment path should be empty.

I do this in terminal all the time.  When you do this, you also need to manually set the DocType.  Here's an example:

ENSEMBLE>set msg = ##class(EnsLib.HL7.Message).ImportFromFile("C:\InterSystems\HL7Messages\ADT_A01.txt")

ENSEMBLE>set msg.DocType="2.3.1:ADT_A01"

ENSEMBLE>write msg.GetValueAt("MSH:9")
ENSEMBLE>write msg.GetValueAt("PID:DateTimeOfBirth.timeofanevent")

The example at this URL in the documentation shows how to create a REST business service which retrieves JSON data, converts it to a proxy object, and then extracts values from the proxy object to store in a response:


Assuming you are retrieving your JSON data from a REST service, your use case is similar.  Instead of storing the values in a response, you would want to create a new request class to hold the values.  Replace pResponse in the example with an instance of your new request class, fill it with data from the JSON proxy object, then send it to a message router component with ..SendRequestAsync.

Then, in your message router, you can add a DTL which transforms your new request class into an ADT_A31 HL7 message.

<PROPERTY DOES NOT EXIST> means your code is trying to reference a class property that does not exist.  The rest of the error message should tell you which property you tried to reference that didn't exist.

After you added those 3 properties to the WeatherResponse class, did you save and compile it?

If you're not able to resolve this, can you post the complete error message?  What property is it telling you doesn't exist?

%Net.SMTP method Send handles connecting to the SMTP server, extracting all the necessary data from %Net.MailMessage, formatting it for SMTP, and writing it to the server.

If you copy this method and modify it to skip the connecting to server portion and instead have it OPEN and USE a file, then all of the write commands (well, $$$WriteLine commands) will write to a file rather than to the SMTP server.  This might be the simplest way to serialize the %Net.MailMessage