Jump to content

Recommended Posts

Hello

I have question about indy,sending and receiving messages from-to ECR-POS(Ingenico),

am i doing it right ?

------send to POS request for Card paying

 

  IdTCPClient1.IOHandler.InputBuffer.Clear;
  IdTCPClient1.IOHandler.Write(buff);

 Timer4.Enabled := true;

 

---------on timer4

 try
  if IdTCPClient1.IOHandler.InputBufferIsEmpty then
  begin
    if IdTCPClient1.IOHandler.CheckForDataOnSource(1000) then
    begin
     bajt := IdTCPClient1.IOHandler.ReadByte;
     bajt := IdTCPClient1.IOHandler.ReadByte;
      IdTCPClient1.IOHandler.ReadBytes(Buffer,bajt - 1,true);

         s := '';
         for i := 0 to bajt - 1 do
           s := s + chr(buffer);
          Memo1.Lines.Add(s);

         Timer4.Enabled := false;
    end else
       IdTCPClient1.IOHandler.InputBuffer.Clear
  end else IdTCPClient1.IOHandler.InputBuffer.Clear;
 except

 end;
 

Share this post


Link to post
Posted (edited)
5 hours ago, boris.nihil said:

I have question about indy

FYI, there is an Indy-specific forum on this site: https://en.delphipraxis.net/forum/35-indy/

5 hours ago, boris.nihil said:

sending and receiving messages from-to ECR-POS(Ingenico),

am i doing it right ?

It is hard to answer that without knowing any details about the particular specification you are coding against.

5 hours ago, boris.nihil said:

IdTCPClient1.IOHandler.InputBuffer.Clear;
IdTCPClient1.IOHandler.Write(buff);

Timer4.Enabled := true;

If you are expecting a response immediately after writing, then why are you using a Timer?  Just read and let it block.  If you are doing this from the main UI thread and don't want to block the UI, then use a worker thread.

Quote

if IdTCPClient1.IOHandler.InputBufferIsEmpty then
begin
  if IdTCPClient1.IOHandler.CheckForDataOnSource(1000) then
  begin
    ...

  end else
    IdTCPClient1.IOHandler.InputBuffer.Clear
 end else IdTCPClient1.IOHandler.InputBuffer.Clear;

Why do you keep clearing the IOHandler.InputBuffer when it is already empty?

Quote

bajt := IdTCPClient1.IOHandler.ReadByte;
bajt := IdTCPClient1.IOHandler.ReadByte;
IdTCPClient1.IOHandler.ReadBytes(Buffer,bajt - 1,true);

s := '';
for i := 0 to bajt - 1 do
  s := s + chr(buffer);
Memo1.Lines.Add(s);

Timer4.Enabled := false; 

Why are you discarding the 1st byte? What does it represent?

 

FYI, you can replace your entire loop with a single call to Indy's BytesToString() function, eg:

var
  Buffer: TIdBytes;
...
IdTCPClient1.IOHandler.ReadBytes(Buffer, bajt - 1, False);
s := BytesToString(Buffer);

Or, you could just use IOHandler.ReadString() instead of IOHandler.ReadBytes(), eg:

s := IdTCPClient1.IOHandler.ReadString(bajt - 1);

 

Edited by Remy Lebeau

Share this post


Link to post
Quote

FYI, there is an Indy-specific forum on this site: https://en.delphipraxis.net/forum/35-indy/

thanks

Quote

It is hard to answer that without knowing any details about the particular specification you are coding against.

 Datagram protocol
Datagram protocol is used over stream-oriented protocols (TCP) to provide information to the receiver of the length of the data being sent.
Datagram protocol forms a packet by adding a header to the payload.
Datagram protocol header contains the length of the payload encoded in two bytes.

Header Format
Header consists of two bytes with the most significant byte first:

Byte   Value
1        Message length/256
2        Message lengt%256

---------------------------------------
Length of data    Header      Packet
7                         0x00 0x07  0x00 0x07 B1 B2 B3 … B7
17                       0x00 0x11  0x00 0x11 B1 B2 B3 … B17
135                     0x00 0x87  0x00 0x87 B1 B2 B3 … B135

 

Quote

If you are expecting a response immediately after writing, then why are you using a Timer?

i need timer (put on 2000 ms), becouse i wait for customer to insert credit card on POS terminal, then POS will sent some message to me,starting with 10xxxxxxx

 

 

Quote

Why are you discarding the 1st byte? What does it represent?

first 2 bytes is size of packet,i think first one is always zero ?

 

Quote

FYI, you can replace your entire loop with a single call to Indy's BytesToString() function, eg:

thanks,i will try it

Share this post


Link to post
Posted (edited)
2 hours ago, boris.nihil said:

Datagram protocol header contains the length of the payload encoded in two bytes.

In that case, your code logic is wrong.  You are throwing away one of the length bytes, so you will only be able to handle packets up to 256 bytes max.  And, based on the examples provided, you should not be subtracting -1 from the length, either.  You are ignoring the last byte in the payload.

 

Try this instead:

var
  s: string;
  len: UInt16;
...
try
  if IdTCPClient1.IOHandler.InputBufferIsEmpty then
  begin
    if not IdTCPClient1.IOHandler.CheckForDataOnSource(1000) then
      Exit;
  end;
  len := IdTCPClient1.IOHandler.ReadUInt16;
  s := IdTCPClient1.IOHandler.ReadString(len);
  Memo1.Lines.Add(s);
  Timer4.Enabled := false;
 except
 end;
2 hours ago, boris.nihil said:

i need timer (put on 2000 ms), becouse i wait for customer to insert credit card on POS terminal, then POS will sent some message to me,starting with 10xxxxxxx

Fair enough, though I would still not advise doing that on the main UI thread to begin with.

2 hours ago, boris.nihil said:

first 2 bytes is size of packet,i think first one is always zero ?

Only for packets with payloads up to 255 bytes in size.  Larger payloads will not have a zero as the 1st byte.  This protocol allows for payloads up to 65535 bytes in size.

Edited by Remy Lebeau

Share this post


Link to post
Quote

len := IdTCPClient1.IOHandler.ReadUInt16;

compiler says error,no such function

 this code works...

-------------------

      bajt := data1.IdTCPClient1.IOHandler.ReadByte;
      bajt1 := data1.IdTCPClient1.IOHandler.ReadByte;
      bajt2 := bajt * $10 + bajt1;
      data1.IdTCPClient1.IOHandler.ReadBytes(Buffer,bajt2,false);


        s := '';
        for i := 0 to bajt2 - 1 do
          s := s + inttohex(buffer,2);

----------------------------

i need a hex, I explode it with 1C delimeter, its easy to handle..

 

 

What AApend parameter means, true or false, what to use in:
data1.IdTCPClient1.IOHandler.ReadBytes(Buffer,bajt2,false);  ?

 

 

 

 

Share this post


Link to post
12 hours ago, boris.nihil said:

compiler says error,no such function

Then you are using an outdated version of Indy and should upgrade. The ReadUInt16() method was added almost a decade ago, in Delphi XE8.

 

In the meantime, you can use the older ReadWord() method instead. 

Quote

 bajt2 := bajt * $10 + bajt1;

That calculation is wrong. You need to multiple by 256 ($100), not by 16 ($10). Better to just use ReadWord()/ReadUInt16() instead. 

12 hours ago, boris.nihil said:

 

12 hours ago, boris.nihil said:

What AApend parameter means, true or false, 

True means it will append the read bytes to the end of the TIdBytes.

 

False means it will store the read bytes at the beginning of the TIdBytes, and will grow the TIdBytes if it is too small. 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×