Read and write data to serial port via openedge/Progress

Asked

Viewed 255 times

2

I have an app that sends the COM4 port a loop like this...

123||60||0||0||0||2||
123||60||0||0||0||2||
123||60||0||0||0||2||
123||60||0||0||0||2||
.
.
.
.
.
123||60||0||0||0||2||

I need to intercept this string to process and return on the same COM4 port that will stop sending this string until starting a new loop with a new string within this format.

I tested with the programs below without success.

http://knowledgebase.progress.com/articles/Article/000031711

def button stop-it label "STOP".

def var stop-sel  as logical   no-undo initial false.
def var lv_tag    as character no-undo.

display stop-it.

on choose of stop-it
    stop-sel = true.

input from com4.
repeat:
   enable stop-it.
   process events.
   import lv_tag.
end.
input close.

But the above program hangs and brings nothing, nor enables the button.

http://www.progresstalk.com/threads/reading-and-writing-to-a-windows-com-port-using-progress.279

def var i-abre                  as integer   no-undo initial 3.
def var i-le-grava              as integer   no-undo initial -1073741824.
def var bit-flags               as integer   no-undo.
def var l-rc                    as logical   no-undo.
def var l-ativo                 as logical   no-undo initial false.
def var i-rc                    as integer   no-undo.
def var i-com-handle            as integer   no-undo.
def var i-cont1                 as integer   no-undo.
def var i-cont2                 as integer   no-undo.
def var m-estr-dcb              as memptr    no-undo.
def var m-com-status            as memptr    no-undo.
def var m-recebe                as memptr    no-undo.
def var m-envio                 as memptr    no-undo.
def var c-estrutura             as character no-undo format "X(28)".
def var c-status-estrut         as character no-undo format "X(5)".
def var c-recebe                as character no-undo format "X(1024)".
def var c-transmite             as character no-undo format "X(1024)".

/* Windows API Procedure Definitions --- */

procedure ClearCommError external "KERNEL32.DLL":
   def input        param nCid      as long   no-undo. /* COMMUNICATIONS HANDLE */
   def input-output param errormask as memptr no-undo. /* POINTER TO STATUS DATA */
   def input-output param comstat   as memptr no-undo. /* POINTER TO STATUS DATA */
/*    def return parameter nReturn as short no-undo. */
end procedure.

procedure CreateFileA external "kernel32.DLL":
   def input  param szDevice             as character no-undo. /* DEVICE NAME */
   def input  param fdwAccess            as long      no-undo.
   def input  param fdwShareMode         as long      no-undo.
   def input  param lpsa                 as long      no-undo.
   def input  param fdwCreate            as long      no-undo.
   def input  param fdwAttrFlags         as long      no-undo.
   def input  param hTemplate            as long      no-undo.
   def return param nCid                 as long      no-undo.
end procedure.

procedure CloseHandle external "KERNEL32.DLL":
   def input param nCid as long no-undo. /* COMMUNICATIONS HANDLE */
end procedure.

procedure GetCommState external "KERNEL32.DLL":
   def input        param nCid    as long      no-undo. /* CONFIG STRING IN DOS MODE FORMAT */
   def input-output param lpDCB   as memptr    no-undo. /* POINTER TO A DCB STRUCTURE */
   def return       param nReturn as short     no-undo. /* RETURN CODE */
end procedure.

procedure SetCommTimeouts external "KERNEL32.DLL":
   def input        parameter nCid       as long   no-undo. /* COMMUNICATIONS HANDLE */
   def input-output parameter lpTimeouts as memptr no-undo. /* TIMEOUT VALUES */
   def return       parameter nReturn    as short  no-undo. /* RETURN CODE */
end procedure. 

procedure FlushComm external "USER.EXE":
   def input  parameter nCid    as short no-undo. /* COMMUNICATIONS HANDLE */
   def input  parameter nQueue  as short no-undo. /* WHICH BUFFER TO FLUSH */
   def return parameter nReturn as short no-undo. /* RETURN CODE */
end procedure.

procedure SetCommState external "KERNEL32.DLL":
   def input        parameter nCid    as long   no-undo. /* POINTER TO A DCB STRUCTURE */
   def input-output parameter lpDCB   as memptr no-undo. /* POINTER TO A DCB STRUCTURE */
   def return       parameter nReturn as short  no-undo. /* RETURN CODE */
end procedure.

procedure ReadFile external "KERNEL32.DLL":
   def input        param nCid         as long   no-undo. /* COMMUNICATIONS HANDLE */
   def input-output param lpBuf        as memptr no-undo. /* POINTER TO A RECEIVE BUFFER */
   def input        param nSizetoRead  as long   no-undo. /* NUMBER OF BYTES TO RECEIVE */
   def input-output param nSizeActRead as memptr no-undo. /* NUMBER OF BYTES TO RECEIVE */
   def input        param nullptr      as long   no-undo. /* NUMBER OF BYTES TO RECEIVE */
   def return       param nReturn      as short  no-undo. /* RETURN CODE */
end procedure.

procedure WriteFile external "KERNEL32.DLL":
   def input        parameter nCid         as long   no-undo. /* COMMUNICATIONS HANDLE */
   def input-output parameter lpBuf        as memptr no-undo. /* POINTER TO A TRANSMIT BUFFER */
   def input        parameter nSizetowrite as long   no-undo. /* NUMBER OF BYTES TO TRANSMIT */
   def input-output parameter nSizeActwrit as memptr no-undo. /* NUMBER OF BYTES TO RECEIVE */
   def input        parameter nullptr      as long   no-undo. /* NUMBER OF BYTES TO RECEIVE */
   def return       parameter nReturn      as short  no-undo. /* RETURN CODE */
end procedure.

procedure COMMTIMEOUTS external "KERNEL32.DLL":
   def input  parameter ReadIntervalTimeout            as long no-undo.
   def input  parameter ReadTotalTimeoutMultiplier     as long no-undo.
   def input  parameter ReadTotalTimeoutConstant       as long no-undo.
   def input  parameter WriteTotalTimeoutMultiplier    as long no-undo.
   def input  parameter WriteTotalTimeoutConstant      as long no-undo.
   def return parameter COMMTIMEOUTS                   as long no-undo.
/*       , *LPCOMMTIMEOUTS; */
end procedure.

/* run ReceiveData (input 5). */
run pi-conecta.
run pi-envia (input 'teste').

/* internal procedure calls*/
procedure pi-conecta:
   /* Porta de comunica‡Æo (COM1) */
   /* \Device\0000006d            */

   def var pi-param-1          as integer no-undo.
   def var pi-param-2          as integer no-undo.
   def var pi-param-3          as integer no-undo.
   def var pi-param-4          as integer no-undo.

   set-size(ComStatStructurePointer)    = 20.
   put-long(ComStatStructurePointer,1)  = 1000.
   put-long(ComStatStructurePointer,5)  = 10.
   put-long(ComStatStructurePointer,9)  = 100.
   put-long(ComStatStructurePointer,13) = 10.
   put-long(ComStatStructurePointer,17) = 100.

   run SetCommTimeouts (CommHandle,
                        input-output ComStatStructurePointer,
                        output nRC).

   run CreateFileA (input 'COM4',
                    input i-le-grava,
                    input pi-param-1,
                    input pi-param-2,
                    input i-abre,
                    input pi-param-3,
                    input pi-param-4,
                    output i-com-handle).

   if i-com-handle < 0 then do:
      message "Handle invalido:" i-com-handle " na procedure pi-conecta"
              view-as alert-box error.
      quit.
   end.
   set-size(m-estr-dcb) = 29.
   run GetCommState (i-com-handle, input-output m-estr-dcb, output i-rc).
   if i-rc <> 0 then do:
      assign c-estrutura = get-string(m-estr-dcb,1).
      put-long(m-estr-dcb,5) = 9600.
      bit-flags = exp(2,9) + exp(2,10).
      put-long(m-estr-dcb,9) = bit-flags.
      put-byte(m-estr-dcb,19) = 8.
      put-byte(m-estr-dcb,20) = 0.
      run SetCommState (i-com-handle, input-output m-estr-dcb,output i-rc).
      if i-rc = 0 then do:
         message "error setting new parameters"
                 view-as alert-box.
      end.
   end.
   else do:
      message "BuildCommDCB failed in pi-conecta"
              view-as alert-box error.
   end.
end procedure.

procedure ReceiveData:
   def input parameter numchars as int.

   def var vm-rec as memptr.
   /* The ReceiveData Variable Will Contain The Data Read From The Serial Port */
   set-size(vm-rec) = 4.
   if numchars > 0 then do:
      set-size(m-recebe) = numchars + 1. /* Max Size of Receive Queue */
      run ReadFile (i-com-handle, input-output m-recebe, numchars,input-output vm-rec,0, output i-rc).
      assign c-recebe = get-string(m-recebe,1).
      if numchars < get-long(vm-rec,1) then do:
         message "Readcomm did not get all characters".
      end.
      set-size(m-recebe) = 0.
   end.
   set-size(vm-rec) = 0.
end procedure.

procedure check-receive:
   def var errmask   as memptr  no-undo.
   def var m-check   as memptr  no-undo.
   def var num-chars as integer no-undo.

   set-size(m-check) = 12.
   set-size(errmask) = 4.
   put-long(m-check,1) = 0.
   put-long(errmask,1) = 0.
   run ClearCommError(i-com-handle,input-output errmask,input-output m-check /*,output i-rc*/).
   num-chars = get-long(m-check,5).
   set-size(errmask) = 0.
   set-size(m-check) = 0.
   return string(num-chars).
end procedure.

procedure pi-envia:
   def input parameter datatosend as char.

   def var TotalSize   as integer no-undo.
   def var m-send      as memptr  no-undo.
   def var retry-count as integer no-undo initial 0.

   set-size(m-send) = 4.
   put-long(m-send,1) = 0.

   do while length(datatosend)>0:
      assign c-transmite = DataToSend
             TotalSize = length(c-transmite).
      set-size(m-envio) = TotalSize + 1.

      put-string(m-envio,1) = c-transmite.
      run WriteFile (i-com-handle,input-output m-envio, TotalSize, input-output m-send,0, output i-rc).
      case true:
         when get-long(m-send,1) LT TotalSize then do:
            message "transmitdata sent " i-rc " of " totalsize
                     " at " time "retry=" retry-count.
            assign retry-count = retry-count + 1.
            datatosend = substring( c-transmite , absolute(i-rc) + 1 ).
            pause 1 no-message.
         end.
         otherwise do:
            datatosend = "".
         end.
      end case.
      set-size(m-envio) = 0.
   end.
   set-size(m-send) = 0.
end procedure.

Someone’s done something like this before and can give me a hint?

  • Make a tour by stackoverflow, learn a little about the rules and good practices. Then edit your question and enter the code of what you’ve tried...

  • Hi Geovane, could you please edit your question and include the links to the code you found on the internet (is it always important to declare the source)? Another thing, it’s not very clear what your specific problem is... Reading from a serial port is a very wide problem, the way to read depends on your environment and the type of data you traffic (that is, you probably won’t find any code ready to solve your problem). I suggest you write a MVCE making it very clear what you are trying to read, from which door, and what error.

1 answer

2

  • I have an application that sends to the COM4 port a loop like this... 123||60||0||0|||0||2|||<br> 123|60||0||0||0||2|||<br> . <br> . <br> . <br> 123|60||0||0||0||2|||<br> I need to intercept this string to process and return on the same COM4 port. The programs I mentioned are at: http://knowledgebase.progress.com/articles/Article/000031711 and http://www.progresstalk.com/threads/reading-and-writingto-a-windows-com-using-progress.279 when using the program that uses input from to access the port, it hangs and the other program also shows me nothing.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.