go to post Jeffrey Drumm · Mar 30, 2021 This might get you closer to what you want, perhaps called from OnProcessMessage() in the service: ClassMethod QueueGetOldest(pQueueName As %String, Output pStatus As %Status) As %String { If ##class(Ens.Queue).GetCount(pQueueName) > 0 { Set tStmt = ##class(%SQL.Statement).%New() set qSC = tStmt.%PrepareClassQuery("Ens.Queue","EnumerateItem") Set tRS = tStmt.%Execute(pQueueName,"") Do tRS.%Next() Set tHdrid = tRS.%Get("MessageId") Set tMsghdr = ##class(Ens.MessageHeader).%OpenId(tHdrid) Set pStatus = $$$OK Return tMsghdr.TimeCreated } Set pStatus = $$$ERROR($$$GeneralError,"Not found") Return "" } It returns the time created of the oldest entry in the queue, or the empty string if the queue is empty or doesn't exist. You could create a variant that would accept a duration argument and return true/false if the duration between the current time and the time of the oldest entry exceeds that.
go to post Jeffrey Drumm · Mar 24, 2021 Hi Scott, You can get the repetition count for a field with the GetValueAt() method: Set tRepCount = msg.GetValueAt("OBX(3):5(*)") You can then iterate over the repetitions in a FOR loop: For tRep = 1:1:tRepCount { If msg.GetValueAt("OBX(3):5("_tRep_")") = tMatchVal { // Do stuff } }
go to post Jeffrey Drumm · Feb 24, 2021 The tilde character ("~") has special meaning in HL7; it is normally used as the field repetition character. If it is being included in a field value as a literal character, it is often converted to an "escape sequence" so that it can be delivered to a downstream system intact rather than interpreted as a delimiter; the escape sequence for the field repetition character is \R\. Is your intended use of the ~ character to function as a repetition delimiter, or is it actually a verbatim part of a field value?
go to post Jeffrey Drumm · Feb 18, 2021 Are you inserting these values into an EnsLib.HL7.Message object? If yes, the standard way of doing this is to first make sure the SPM field you're working with is defined as repeating in the message schema (DocType), then iterate through your list of field values to be inserted. Assuming your message object is tMsg: Do tMsg.SetValueAt(Modifier1,"SPM:9(1)") Do tMsg.SetValueAt(Modifier2,"SPM:9(2)") Do tMsg.SetValueAt(Modifier3,"SPM:9(3)") This will automatically use the repetition separator to delimit the values in SPM field 9. Note that the path supplied for the SPM segment/field will vary based on your specific schema definition.
go to post Jeffrey Drumm · Feb 15, 2021 You sure can. You can find the documentation for adding settings to business hosts here.
go to post Jeffrey Drumm · Feb 8, 2021 02/08/21-09:17:52:754 (8272) 2 [Generic.Event] Too many Cores (12) for InterSystems IRIS Community License. The Community Edition license is invalid for the number of cores your Windows 10 host has. It supports a maximum of 8 cores, and you appear to have 12.
go to post Jeffrey Drumm · Feb 8, 2021 You'll need to install the CSP gateway component on the Apache server, but not IRIS itself.
go to post Jeffrey Drumm · Feb 8, 2021 As is USER> w $system.Util.InstallDirectory()_"lib" There's also a LibPath entry in IRIS.cpf, but I'm not sure it's the same. But you can get it: %SYS> do ##class(Config.config).Get(.props) %SYS> write props("LibPath") Unfortunately on the IRIS server I'm working with it's empty ...
go to post Jeffrey Drumm · Jan 15, 2021 This question is more than 2 1/2 years old now, but I guess I missed it when it was posted. Regardless, the issue is that "?" is the match operator that "Matches" represents, and is not part of the pattern itself. Your match pattern should not include the "?" character.
go to post Jeffrey Drumm · Dec 24, 2020 I'm thinking that the value you provided for ElementName in the service's configuration is incorrect. Your class definition also needs to match the structure of the repeating element, not the entire XML document. Here's an example XML structure: <Persons> <Person> <LastName>Drumm</LastName> <FirstName>Jeff</FirstName> <FavoriteColor>Red</FavoriteColor> </Person> <Person> <LastName>Herlick</LastName> <FirstName>Blakely</FirstName> <FavoriteColor>Teal</FavoriteColor> </Person></Persons> The classname you'd create would be something like User.Custom.Person, with properties FirstName, LastName and FavoriteColor. In the service's ElementName field, you'd enter Person. When the file is read, each Person element from the XML would end up in a separate message. You can then filter in the routing rule by using the variables Document.FirstName, Document.LastName, etc. and transform it in the DTL by selecting the Persistent Class User.Custom.Person as the source and your HL7 schema as the target. Make sense?
go to post Jeffrey Drumm · Dec 24, 2020 Hi Blake, Can you provide a bit more detail? If you need to create an individual HL7 message for each repeating element in the XML document, my answer here is probably the easiest way to get there. If there's a "master/detail" relationship within the XML, though, you'll need to handle that in a BPL, and perhaps still "chunk" the XML before handing it off to the BPL if there are multiple elements with master/detail relationships. You'd do that with the XML Object file service mentioned in the link (assuming you're getting these XML documents as local files ... there's also an FTP version of the service). There are tutorials on BPLs in ISC's Learning library.
go to post Jeffrey Drumm · Oct 14, 2020 Hi Nora! Long time Something like this should do the trick, assuming the file to be appended to is named "spoo.txt" and the file from which you're appending is named "fleem.txt": Set tOut = ##class(%File).%New() Set tIn = ##class(%File).%New() Set tSC = 1 Set tOut.Name = "spoo.txt" Set tIn.Name = "fleem.txt" Set sc = tOut.Open("WA") Set:$$$ISERR(sc) tSC=$$$ADDSC(tSC,sc) Set sc = tIn.Open() Set:$$$ISERR(sc) tSC=$$$ADDSC(tSC,sc) Quit:$$$ISERR(tSC) tSC While 'tIn.AtEnd { Set sc=tOut.Write(tIn.Read()) Return:$$$ISERR(sc) sc } Do tIn.Close() Do tOut.Close() Return $$$OK
go to post Jeffrey Drumm · Sep 3, 2020 Here's a method that, once created and compiled, will appear in your dropdown list of functions in the rule editor: Class User.Util.DateTime Extends Ens.Rule.FunctionSet { ClassMethod DaysPrior(pDays As %Integer) As %String { Return $ZDATE($H - pDays,8) } } You'd use it in your rule like this: Caveat: The birthdate is assumed to be valid and 8 characters in length. If there's a possibility that you would get an invalid or missing date, the ">" comparison will not be valid.
go to post Jeffrey Drumm · Jun 26, 2020 GetAdapterSettingValue() may give you what you want. The Type parameter isn't needed. Set archiveFilePath=##class(Ens.Director).GetAdapterSettingValue("ReadPDFFileService","ArchivePath",.status) There's a corresponding GetHostSettingValue() method for non-adapter settings that works similarly. Both seem to supply the System Default Setting when the setting is unvalued in the production.
go to post Jeffrey Drumm · Jun 2, 2020 The schema doesn't seem to match the structure of the message you've supplied; the OBRuniongrp group should be a repeating group and indicate such with parentheses (i.e. OBRuiniongrp()). Assuming that's fixed in the schema, you should be able to get at the fields in question in repeating OBR segments with something like: Set tStudy = 0 // Get count of OBR segments Set tOBRCnt = request.GetValueAt("ORCgrp(1).OBRuniongrp(*)") // Loop through OBRs and evaluate field contents For tIter = 1:1:tOBRCnt { If request.GetValueAt("ORCgrp(1).OBRuniongrp("_tIter_").OBRunion.OBR:UniversalServiceIdentifier.Identifier") = "match_value" { Set tStudy = 1 } } If tStudy { ...insert action to take here... } The above may need to be modified to use context variables if it's being used in a BPL.
go to post Jeffrey Drumm · Apr 20, 2020 Rather than: s target.{ORCgrp(k1).OBRgrp(k2).OBXgrp(k3).NTE(iNteCnt)} sTmp Try: d target.SetValueAt(iNteCnt, "ORCgrp("_k1_").OBRgrp("_k2_").OBXgrp("_k3_").NTE("_iNteCnt_"):1") d target.SetValueAt(sTmp, "ORCgrp("_k1_").OBRgrp("_k2_").OBXgrp("_k3_").NTE("_iNteCnt_"):3") Assuming you want the value in the 3rd field of the NTE. You should also change the value stored in sNTE to: source.{ORCgrp(k1).OBRgrp(k2).OBXgrp(k3).NTE(1):3} If there's only one NTE segment in each OBXgrp of the the inbound message.
go to post Jeffrey Drumm · Apr 15, 2020 Building an interface in Ensemble would require essentially emulating the printing protocol used by Meditech (lpr/lpd?). While that might be fun, I don't know that it's the best use of your time Depending on your OS platform, it might be possible to route Meditech's printer output to files. This would be done by configuring a custom printer definition on either the Ensemble host or a host that Ensemble has file (ftp/sftp/cifs/etc.) access to. For Unix/Linux, this isn't terribly hard to do with lpd, and I imagine it can be done with CUPS as well. I know Windows can function as an lpd server, but I'm not sure how you would get its output routed to a file. Once the printed output is in file form, you could then create a file service in Ensemble to pick up and process it.
go to post Jeffrey Drumm · Apr 3, 2020 The documentation is available both in the DTL editor when you use the Exists() method in the Expression Editor for a rule: And in the Class Reference for Ens.Rule.FunctionSet -- the Exists() Method: The Class reference is clearer about the table argument being a quoted string.
go to post Jeffrey Drumm · Feb 25, 2020 Did you get an actual compilation error, or just an error indicator in the expression editor? In my case, the dialog box shows the expression indicated an error, but it doesn't cause a compilation problem. I don't have any sample messages to test with at the moment, so I'm not sure it will actually work ...
go to post Jeffrey Drumm · Feb 19, 2020 I set up a test scenario based on your criteria. I created a service, HL7 router process and 3 operations: Service: HL7 MLLP, target HL7 Router, AckMode=Application Process: HL7 Router, ForceSyncSend: True, ReplyCodeActions: E=F Target Operation 1: HL7 File Out Target Operation 2: Custom Operation that returns an HL7 NAK, sets IsError to 1, logs an error code of 5001 with text "Forced NAK", ReplyCodeActions: E=F Target Operation 3: HL7 File Out Observations: Message arrives in router process Routes to Operation 1, completes successfully Routes to Operation 2, receives error Router responds to Service with Error; shuts down ... no message delivered to Operation 3 Service returns NAK to sending application Message remains queued for Router Isn't this what you would want to happen?