Connect to Cloverleaf tcp/ip thread with tcl socket command

Clovertech Forums Cloverleaf Connect to Cloverleaf tcp/ip thread with tcl socket command

Tagged: 

  • Creator
    Topic
  • #115468
    Robert Kersemakers
    Participant

      Has anybody connected to a Cloverleaf tcp/ip thread with a piece of tcl code using the socket command? Let me explain further.

      We have a QRY process where a system can send a QRY^A19 (or QRY^Q01) message and will receive a ADR^A19 message back. Very basic stuff.
      To test this interface, we have a test-thread which is configured with tcp/ip protocol. This thread is input with one patientnumber. This input (an FRL of one field) is then translated into a QRY^A19 message and sent to our HIS. The response is an ADR^A19 which is returned as reply. We use this test-thread with hcitcptest:

      hcitcptest -h localhost -t 4 -p 8303

      You can then type in the desired patientnumber and see the ADR^A19 reply coming back.

      What I would like to do is write a piece of tcl script whose input is an HL7 message (mostly an ORU with a result) out of which I will extract the patientnumber. Now I want to check this patientnumber for validity, so I would like to connect to the test-thread, send out the patientnumber and receive the ADR^A19. Based on the reply I will then decide whether to forward the result, or send out an email to users that they have (once again) used an invalid patientnumber.

      So I have been fooling around (changed the tcp-ip setting of the test-thread to Data Type ‘Ascii’ and length ’10’, inclusive) and got to to this:

      set chan [socket localhost 3761]
      fconfigure $chan -buffering none -blocking 1
      puts $chan “0000000020010101CA20”
      flush $chan
      set answer {}
      while {[gets $chan line] >= 0} {
      echo “line: <$line>”
      lappend answer $line
      }
      #set answer [gets $chan]
      echo “length answer: <[string length $answer]>”
      echo “answer: <$answer>”

      Output is this:

      line: <       747MSH|^~\&|PI|REC_FAC|CL|SIEMENS|20200212170006||ADR^A19|20|P|2.4>
      line: <MSA|AA|20>
      line: <QRD|20200212170006|R||20||||010101CA20|DEM>
      line: <PID|1||010101CA20^^^^PI~999900456^^^NLMINBIZA^NNNLD||Stanton&&Stanton^Shani^Shani^^^^L||19001221|M|||Verlengde Wilhelminastraat 21&Verlengde Wilhelminastraat 21^^Hoensbroek^^6431XN^NL||06-12345678^PRN^PH||||||||||X|||||||N|N>
      line: <ROL|1|UP|PP^Primary Care Provider|HA099999^NIET GEBRUIKEN Test Edifact^.|||||||Dr H Vd Hoffpln 1&Dr H Vd Hoffpln 1^^Geleen^^6162 BG^NL>
      line: <PV1|1|O|||||||||||||||||||8|||3~3~3~3~3~3~3~3~3~3~3~3~3~3|18000101|8~8~8~8~8~8~8~8~8~8~8~8~8~1>
      line: <OBX|1|ST|PM^Pacemaker||||||||F>
      line: <OBX|1|ST|ALL05^Overige allergieen||||||||F>
      line: <OBX|1|ST|IMM 01^Allergie immunomodulantia||||||||F>
      line: <OBX|1|ST|ALL01^Jodium allergie||||||||F>

       

      Each line (ended by <CR>) is sent separately, with the first line starting with the length encoding of the message. But the script doesn’t end: there is no EOF in the message so my guess is I will need to program using the length encoding of the first line and then read each line until the message has ended.
      Also took a look if I could use hcitcptest, but it’s really only for online/interactive use.

      So maybe someone else has done this before and doesn’t mind sharing his/her efforts. Or has some information that I could use. Thanks in advance!

       

      Zuyderland Medisch Centrum; Heerlen/Sittard; The Netherlands

    Viewing 4 reply threads
    • Author
      Replies
      • #115479
        Peter Heggie
        Participant

          I did something similar, as far as connecting to an input thread, but some of the options I’m using are different – it does not mean I know what I’m doing though! I got it to work but I think there was a byte or two ‘leftover’. And I just waited for a response and discarded it, mostly because the thread I was sending to wanted to send an ACK and I needed to consume it. I don’t know much about the ‘buffering’ or ‘blocking’ options.

          Peter

          ######################################################################
          # Name:      prl_status_tcp
          # Purpose:   Put information into a tcp/ip connection. This is called
          #            in Send_OK or in a batch script. That is all it does.
          #            A pair of threads will be on the receiving end of this
          #            tcp socket – getting the tcp/ip message and then sending
          #            it to the outbound thread which updates a database.
          #
          #            This is a called proc.
          #
          #            Specific use:
          #            This updates the audit_prl SQL Server table which tracks
          #            prl message delivery.
          #
          #            The values are all passed in a list:
          #
          # UPoC type: tcl
          #
          # History:   2016/06/30 PCH created
          #

          proc prl_status_tcp { debug module flist } {

          set debug 2
          set module “$module.prl_status_tcp:”
          if {$debug > 1} {echo “$module debug”}

          if {$debug > 1} {echo “$module flist: $flist”}

          lassign $flist uid tstamp interface facility status note type server path name size time
          set status “”
          set mlp_begin “\x0b”
          set mlp_end “\x0d\x1c\x0d”

          if {$debug > 1} {echo “$module uid: $uid tstamp: $tstamp interface: $interface facility: $facility status: $status note: $note”}
          if {$debug > 1} {echo “$module type: $type server: $server path: $path name: $name size: $size time: $time”}

          # join list to set file content
          set tcpdata [join “$flist” “|”]
          if {$debug > 1} {echo “$module tcpdata: $tcpdata”}

          set tcpdata “$mlp_begin$tcpdata$mlp_end”
          if {$debug > 1} {echo “$module tcpdata with mlp: $tcpdata”}

          # send data to tcp/ip socket
          set tcpaddr [hcitbllookup “general_parms” “fr_batch_status_tcp_address”]
          set tcpport [hcitbllookup “general_parms” “fr_batch_status_tcp_port”]

          set chan [socket $tcpaddr $tcpport]     ;# Open the connection
          puts -nonewline $chan “$tcpdata”         ;# Send a string
          flush $chan                              ;# Flush the output buffer
          set response [gets $chan]                ;# Receive a string
          close $chan                              ;# Close the socket
          if {$debug > 1} {echo “$module tcp ip chan $chan send response: $response”}

          }

          Peter Heggie

          • #115485
            Robert Kersemakers
            Participant

              Thanks Peter.

              In my case the response is the key, so that is where I’m struggling. Weird thing is that ‘[gets $chan]’ will read a line of data and even hack off the ending <CR>. Was wondering if it was possible to get the data character for character.
              As in your example, I could use the MLLP start/stop characters as well to decide where the the message starts and ends.

              Was just fiddling around with buffering and blocking; until now they serve no purpose.

              Zuyderland Medisch Centrum; Heerlen/Sittard; The Netherlands

          • #115486
            Robert Kersemakers
            Participant

              Using the command ‘read’ instead of ‘gets’ works a lot better for my needs. I now have something decent running where the reply is completely read. Here is the code:

              set chan [socket localhost 3761]
              fconfigure $chan -buffering none -blocking 1
              puts $chan “0000000020010101CA29”
              flush $chan
              set msglength [expr [string trim [read $chan 10]] – 10]
              echo “msglength: <$msglength>”
              fconfigure $chan -blocking 0
              set answer [read $chan $msglength]
              echo “answer: <$answer>”
              close $chan

              And the output:

              msglength: <167>
              answer: <MSH|^~\&|PI|REC_FAC|CL|SIEMENS|20200213115546||ADR^A19|36|P|2.4
              MSA|AE|36|Patiënt voor interne ID 010101CA29 niet gevonden
              QRD|20200213115546|R||36||||010101CA29|DEM
              >

               

              Blocking is quite crucial. I have to turn it on at first, but need to turn it off after reading the message length. Any other way gives no result.

              This works for me. Will use this to build a decent tcl-script. Am aware that I have to make sure the connection works and the received reply is the correct reply.

              Zuyderland Medisch Centrum; Heerlen/Sittard; The Netherlands

            • #115529
              Robert Kersemakers
              Participant

                Last update.
                The answer back was not correct: all <CR> ending a segment were replaced with <CR><NL>. By adding a ‘-translation binary’ this problem was solved.

                 

                set chan [socket localhost 3761]
                fconfigure $chan -buffering none -blocking 1
                puts $chan “0000000020010101CA29”
                flush $chan
                set msglength [expr [string trim [read $chan 10]] – 10]
                echo “msglength: <$msglength>”
                fconfigure $chan -blocking 0 -translation binary
                set answer [read $chan $msglength]
                echo “answer: <$answer>”
                close $chan

                Zuyderland Medisch Centrum; Heerlen/Sittard; The Netherlands

              • #116342
                lauri buijs
                Participant

                  Hi Robert,

                  We don’t use this method you are describing I’m sorry I can’t help you with that.

                   

                  But I think we use something different for the same problem.

                  In the CWZ Nijmegen we will call this “enrichment / verrijking” procedure and use it to check for data in another our EHR while the orders are coming from a different facility.

                  I basically make a new QRY message on the (national) IDnumber, store the original message in a sql lite database,

                  After the qry, I use the result of the qry to use take the appropriate route ( positive QRY-result is an other route than a negative QRY-result).

                  Then I pull the original message from the database (based on multiple fields) and start to enrich the original message and sent it to the right location.

                  You don’t want to enrich the message (I think)  but the making of the qry and the receiving of the qry and the routing are the same..

                  If this is what you are after.. please sent me a message ( in dutch).

                  • This reply was modified 4 years, 8 months ago by lauri buijs.
                  • This reply was modified 4 years, 8 months ago by lauri buijs.
                • #116390
                  Robert Kersemakers
                  Participant

                    Hi Lauri,

                    Yes, this is the same issue we talked about earlier. I wanted to do something generic to solve this. On the whole I was able to get this working (connecting to a QRY-thread with tcl and getting the answer whether or not a patient id is valid). But the problem is the timeout: if you don’t get a response from the qry, the the whole process just stops.
                    I tried to build in a timeout (filevent etc) but in the end I couldn’t make it work.

                    So I am now trying a different/your approach: receive an ORU and turn the message into a ADR^Q01; add the original ORU as USERDATA to the Q01. Send the Q01 to a Cloverleaf QRY-thread and receive the answer. If the answer is valid, then send the original message on its way for further processing; if not the kill the original message and send an email to the users. If there is no QRY-answer withing a timeout, then the ORU is also send on its way for further processing.

                    I’m getting there, but want to make things as generic as possible so I can reuse this for all incoming ORU/report-threads.

                    Will keep you informed of how I’m doing on this.

                    Zuyderland Medisch Centrum; Heerlen/Sittard; The Netherlands

                Viewing 4 reply threads
                • You must be logged in to reply to this topic.