Jeffrey Drumm · Jul 4, 2024 go to post

@Enrico Parisi's observation is the most likely reason for the failure. You can obtain the credentials (assuming you've set them up in Interoperability | Configure | Credentials) with
 

Set tCreds = ##class(Ens.Config.Credentials).%OpenId(..Adapter.Credentials,,.tSC)
Return:$$$ISERR(tSC) tSC

The tCreds.Username and tCreds.Password properties are available on success.

Jeffrey Drumm · Jul 4, 2024 go to post

The Connect() method returns a %Boolean, not an %Status. You should check the ReturnCode and ReturnMessage properties to determine why it's failing.

Jeffrey Drumm · Jul 3, 2024 go to post

The new editor doesn't support that, at least yet. If you'd prefer to have the original rule editor launch when editing a rule, you can disable the new editor's web application /ui/interop/rule-editor through the Management Console via System Administration | Security | Applications | Web Applications.
 

Jeffrey Drumm · Jun 12, 2024 go to post

Odd. I just ran your exact query on IRIS for Health 2023.3 and it executed successfully.

The error message suggests that a macro isn't defined, specifically $$$vaDataSegName, which is found in EnsHL7.inc (among others). Since you're working specifically with HL7 messages I suspect that include file is not available to the namespace in which you're running the query.

Jeffrey Drumm · May 26, 2024 go to post

Looking through the HL7 2.5 OML_O21 structure as supplied by InterSystems, you'll find that there's a nested PIDgrpgrp() under ORCgrp().OBRgrp() that has a subordinate ORCgrp(). It looks like the parse is attempting to match on the required OBR segment in the nested PIDgrpgrp().ORCgrp().

You have a couple of options ... both of which require a custom schema to match your message. The first is to make the OBR segment in the PIDGrpgrp().ORCgrp() optional; the second is to remove the PIDgrpgrp() grouping entirely in the custom schema.

EDIT: The first option doesn't work since the ORC matches on the optional ORC segment in the nested PIDgrpgrp.ORCgrp(), which makes it attempt to match on the required PIDgrpgrp.ORCgrp().OBXgrp().

Jeffrey Drumm · May 20, 2024 go to post

This is what DTLs are for. The example below shows a scenario using HL7 2.5.1's ORU_R01 message structure, where each OBX segment may be followed by one or more NTE segments. The OBX Set ID, Value Type and Observation Value fields are populated; the first by the value of tObxCounter, the second by the string "TX" and the third by the contents of the Note field. The highlighted area demonstrates the updating of newly added OBX segments with the contents of corresponding NTE segments.

Jeffrey Drumm · Apr 18, 2024 go to post

The ISCAgent is available through the online distribution link at the WRC site, in the "InterSystems Components" category. The oldest version available is 2018.1, but it may work for you.

Jeffrey Drumm · Mar 12, 2024 go to post

OnGetConnections() should return an array in the first (Output) argument, indexed by the names of the target process(es) and/or operation(s). The second argument is the production item object passed by the invocation of the method from the web ui.

Here's an example that scans the business process settings for any setting that ends with "ConfigName" or "ConfigNames" and sets the pArray argument appropriately:

ClassMethod OnGetConnections(Output pArray As %String, pItem As Ens.Config.Item)
{
	#dim tSetting As Ens.Config.Setting
	Do ##super(.pArray,pItem)
   	For l=1:1:pItem.Settings.Count()
	{
		Set tSetting = pItem.Settings.GetAt(l)
		If ($LOCATE(tSetting.Name,"ConfigNames?$") && pItem.GetModifiedSetting(tSetting.Name,.tValue))
   		{
			For i=1:1:$L(tValue,",") 
			{
				Set tOne=$ZStrip($P(tValue,",",i),"<>W")
				Continue:""=tOne
				Set pArray(tOne)=""
			}
		}
	}
}
Adjust the match string in the $LOCATE() function if you're using custom setting name(s) for the target(s).
Jeffrey Drumm · Jan 30, 2024 go to post

I'd suggest using some other directory than /tmp as the root of the source path. And I would also recommend installing it as root rather than a user with some elevated privileges. You'll be specifying the account under which it will actually run later, during the install.

Jeffrey Drumm · Jan 19, 2024 go to post

As mentioned by @Alexander Pettitt, xfs is recommended, but ext4 is supported as well.

I've used both for LVM2 LVs on RedHat at multiple high-volume customers without issue. For my personal development environments I use Ubuntu 22.04 with LVM2 and ext4 LVs.

Jeffrey Drumm · Jan 16, 2024 go to post

It's defined in Ensemble.inc ... but I'm not sure that's what you're looking for. The output should show in the Event log.

#define sysTRACE(%arg)          $$$catTRACE("system",%arg)
#define catTRACE(%cat,%arg)     Do:$$$DoTrace ##class(Ens.Util.Trace).WriteTrace(%cat,$$$CurrentClass,$$$CurrentMethod,%arg)
Jeffrey Drumm · Jan 16, 2024 go to post

Add a code rule at the end of the DTL that contains:

 Write "<pre>"_target.RawContent_"</pre><hr>"

Run the DTL Test and the raw message output will show above the HTML-formatted message.

Disable the rule when you're satisfied with what you're getting.

Jeffrey Drumm · Jan 4, 2024 go to post

The executable should be here:

C:\Program Files (x86)\Common Files\InterSystems\Agent\ISCAgent.exe

Its properties (via Windows Explorer) show the version:

Jeffrey Drumm · Dec 15, 2023 go to post

IRIS For Health includes ASTM E1394-97 / LIS02-A2 structures for mapping to many formats using a DTL, including HL7v2.5.1. It also includes a service class for handling ASTM files (EnsLib.EDI.ASTM.FileService).

Jeffrey Drumm · Dec 10, 2023 go to post

Double check the <install-dir>/mgr/cacheodbc.ini file. I don't think changing the shared object file should have any effect on the visibility of the DSN in the Management Console, but I could be wrong.

Jeffrey Drumm · Dec 10, 2023 go to post

I experienced a similar issue when configuring the MSSQL ODBC driver for IRIS. It appears as though the default odbcgateway.so is 32 bit, and I was able to get it working through the following steps:

  1. Change the working directory to Caché's /<install-dir>/bin
  2. Copy odbcgateway.so to odbcgateway32.so
  3. Copy odbcgatewayur64.so to odbcgateway.so
Jeffrey Drumm · Nov 21, 2023 go to post

The NTE segment is commonly used for plain-text "notes" containing descriptive data that doesn't conform to the structured format used for most other data in HL7 messages. It could certainly be used for the storage of base64-encoded binary data, and the likely candidate for that would be the NTE:3 Comment field.

If the base64 content is less than ~3.5MB in size, it can be assigned directly to that field in a DTL or using the SetValueAt() method of the message object (Note: the HL7 specification does not define a maximum length for the Comment field, but there are considerations for IRIS storage that need to be handled appropriately). If larger than 3.5MB, it must be stored using the StoreFieldStreamRaw() method of the EnsLib.HL7.Message object (there is also a StoreFieldStreamBase64() method but it's not applicable if your data is already in base64 format). If you must use the StoreFieldStreamRaw() method, note that it must be the last method called against the NTE segment as it makes the segment immutable.

The recipient of the ORL_O22 message must be informed of this atypical use of the NTE segment so that it can be handled appropriately.

Jeffrey Drumm · Nov 20, 2023 go to post

You can use the "*" shorthand for obtaining a count of the number of repeating segments (or fields, or groups) in a when clause. Anything greater than 0 evaluates to "true," so adding a Not() around the expression negates that:

Note: The original reply had Document.DocTypeName rather than Document.Name as the first part of the condition expression. The DocTypeName property refers to the message structure, not the actual message trigger event. That's in the Name property.

Jeffrey Drumm · Nov 8, 2023 go to post

You're logging on to the sftp server as user test_user, but attempting to write a file to C:/user/testuser/desktop/orders/. Are you sure that's the correct path for that user? My suspicion is that it's a local permissions issue and not a problem with Caché's sftp support.

I'm not a Solarwinds user/expert; does it have anything useful in its log(s)?

Jeffrey Drumm · Nov 6, 2023 go to post

If the server you're connecting to is reasonably up-to-date on security patches, it's very likely that you will be unable to connect from Caché 2016.1 unless you can get the administrator of that system to enable some older (and less secure) cypher suites.

Jeffrey Drumm · Oct 11, 2023 go to post

Global subscripts have a limit of 511 characters, and Exists() doesn't like anything larger. You'll need to $EXTRACT() the first 510 characters from the field to a context variable as suggested in my previous comment and pass that as the string argument in the Exists() method.

Jeffrey Drumm · Oct 11, 2023 go to post

If the content of the field that contains the base64-encoded PDF is greater than the maximum string size in IRIS, it will be stored as a stream.

I've written a custom function that will extract the full content of a message containing such a value; it was originally created to support fetching large HL7 messages in HL7 Spy. You can download it here: http://www.hl7spy.com/downloads/HICG_HL7.xml. I've been asked to add it to the OEX repository, but I just haven't gotten around to that yet ...

I'm not sure how the SQL Editor in the management console will handle a query that uses that function, though. It will likely cause some interesting behavior 😉

The specific SQL function in that class is HICG.GetBigMsg(<messagebodyid>).

Jeffrey Drumm · Oct 11, 2023 go to post

Can you share the error message generated by the BPL when it terminates?

You should be able to assign the return value of $EXTRACT(request.{OBX:5},1,510)}* to a context variable and use it in place of the original OBX:5 path in the lookup function. However, if the OBX:5 is longer than the maximum string size in IRIS (i.e. it's a stream), you may  need to include logic to check for that, then read just the first 510 bytes.

* The path to the OBX segment is likely different than what's in my example ... you'll need to supply the correct path.

Jeffrey Drumm · Sep 15, 2023 go to post

I"m assuming you're talking about HL7 here ...

InterSystems does a bit of magic in the background to display the Message Body fields in the message viewer, and it's not immediately available to you. However, I've written a custom SQL function that fetches the field at the supplied path (you'll need supply the path as its defined by the Schema/DocType of the message).

Example:

SELECT TOP 100 head.ID As ID,
        {fn RIGHT(%EXTERNAL(head.TimeCreated),999 )} As TimeCreated,
        head.SessionId As Session,
        head.Status As Status,
        head.SourceConfigName As Source,
        head.TargetConfigName As Target,
        HICG.GetMsg(head.MessageBodyId,'MSH:9') As MessageType
    FROM
        %IGNOREINDEX Ens.MessageHeader.SessionId Ens.MessageHeader head
    WHERE
        head.SessionId = head.%ID
        AND head.MessageBodyClassname = 'EnsLib.HL7.Message'
        AND head.SourceConfigName = 'SourceBusinessHostName'
    ORDER BY
        head.ID Desc

You can download the class here: http://www.hl7spy.com/downloads/HICG_HL7.xml

Jeffrey Drumm · Sep 8, 2023 go to post

I don't know of any other attributes, and increasing logging may turn up something but hasn't proved useful in my experience.

If your servers are reporting occasional disconnect errors, that's not necessarily a network issue, or even something to worry about. The mirror members may report disconnections due to things like snapshots/backups where one or more hosts are momentarily suspended by the hypervisor in a virtualized environment, or updates to the OS that might stop/start services as part of the update process. It's important to remember, though, that the arbiter is designed to operate optimally in a low-latency, same network, same data center scenario. If your mirrored hosts are spread across a WAN, you're asking for errors.

Jeffrey Drumm · Sep 7, 2023 go to post

That setting allows you to specify an adapter address over which arbitration traffic will flow. It's a local address for situations where the arbiter server may have multiple adapters on different networks.

The IRIS servers establish the arbiter connection rather than the other way around, and you can have multiple mirror pairs us a single arbiter instance.

The ISCAgent is normally installed by default with IRIS, but may not be activated. On my mirrored servers, it's active, but I don't remember whether that happened automatically as part of the setup process, or I did it manually.

No allow list that I'm aware of, but if you want to restrict access to ISCAgent ports, add an adapter to each host, connected to a VLAN that is not routeable from outside that network. Configure application_server.interface_address to use it. You could also use the same network for mirror journal transmission/communication, and leverage QoS to allocate a fixed minimum amount of bandwidth that would be unavailable to other network traffic.

Jeffrey Drumm · Aug 28, 2023 go to post

You can explicitly exclude '%' schemas with the pattern "\%*" in the Exclude list: