Re: [Lazarus] Usage of Serial in a testing program?

2018-09-10 Thread Bo Berglund via Lazarus
On Mon, 10 Sep 2018 19:49:39 +0200, Giuliano Colla via Lazarus
 wrote:

>Il 10/09/2018 17:30, Bo Berglund via Lazarus ha scritto:
>> Unfortunately not possible in the real case because the file transfer
>> protocol of the device only sends a header with the count of the data
>> to follow and then streams all of the bytes
>
>I don't know how your application is built, but if the origin is an ftp 
>transfer, then data are sent in small packets. It would appear that you 
>somehow get the ftp data and send them to a serial line. It is at that 
>point of the processs that you should create your records to send them 
>individually via the serial line.
>
No FTP!
What I meant is that the device I want to communicate with has a
proprietary serial protocol and it can do file transfers too.
The protocol is delimited and checksummed, but when a file is
transferred there is only one block of file data in the middle of the
transfer and it could be up to 1 Mbytes (the memory limit of the
device).

My application is meant to test WiFi<=>Serial converters to evaluate
those we could use with the data device. So I want to run data through
the unit under test in both direction to verify that it is going to
work in the real environment. In real use the data device is connected
by RS232 wire to the Serial to WiFi converter and a device controller
is hooked in via a TCP socket server on the converter.

The test application implements both endpoints since it aims to check
out the converter itself.

So I am dealing with one enpoint as a TCP socket (using Indy here) and
the other is the serial line where I am trying to use the Serial.pp
unit since it is built-in.
Once it is set up I will push a lot of data through and look at the
performance.

But now I will be off travelling for a week...


-- 
Bo Berglund
Developer in Sweden

-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Usage of Serial in a testing program?

2018-09-10 Thread Bo Berglund via Lazarus
On Mon, 10 Sep 2018 19:44:22 +0200, Giuliano Colla via Lazarus
 wrote:

>Il 10/09/2018 17:30, Bo Berglund via Lazarus ha scritto:
>
>> This seems only to deal with ports 1..9, what about the higher
>> numbered ports 10..255?
>> And would it not be a long execution time for testing all 255 possible
>> com ports on Windows?
>In my experience both Linux and Windows if you connect a new serial 
>device do set a port number just higher than the previous one already there.

On Windows7 at least every time you attach a serial2usb dongle into a
different USB port than before it creates a new COM port with a higher
number. And this port is sticky on the PC too, it remains "taken".
So after a few years (my laptop is from 2011) it stacks up and even
though I have currently only attached 6 such converters (one is a
4-way) the com port numbers are 29-30-31-32-33-34...

>This means that you'll have to deal with higher numbers only if you have 
>more than 9 serial lines in your platform, which is a bit unlikely. Not 
>to consider the likelihood of a platform with 200 serial lines!

I would eventually get there if I continue to unplug and re-plug these
dongles...


-- 
Bo Berglund
Developer in Sweden

-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Usage of Serial in a testing program?

2018-09-10 Thread Giuliano Colla via Lazarus

Il 10/09/2018 17:30, Bo Berglund via Lazarus ha scritto:


I hope that it helps.

Yes it does, but it would have been even better if not full of HTML
tags and stuff. I have edited out most but I guess there are some
still left...
For example inside the code there may be some things like  rather
than >

Sorry, I forced HTML for better readability.
But you may easily extract the clean text (without  and such) by 
creating an empty html file (whatever.html), and opening it with 
LibreOffice or OpenOffice. Then you may copy and paste into it the text 
from the e-mail, and finally save it as a pure text fle (whatever.txt). 
It is much faster and safer than manual editing.


Giuliano

--
Do not do to others as you would have them do to you.They might have different 
tastes.

-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Usage of Serial in a testing program?

2018-09-10 Thread Giuliano Colla via Lazarus

Il 10/09/2018 17:30, Bo Berglund via Lazarus ha scritto:

Unfortunately not possible in the real case because the file transfer
protocol of the device only sends a header with the count of the data
to follow and then streams all of the bytes


I don't know how your application is built, but if the origin is an ftp 
transfer, then data are sent in small packets. It would appear that you 
somehow get the ftp data and send them to a serial line. It is at that 
point of the processs that you should create your records to send them 
individually via the serial line.


--
Do not do to others as you would have them do to you.They might have different 
tastes.

--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Usage of Serial in a testing program?

2018-09-10 Thread Giuliano Colla via Lazarus

Il 10/09/2018 17:30, Bo Berglund via Lazarus ha scritto:


This seems only to deal with ports 1..9, what about the higher
numbered ports 10..255?
And would it not be a long execution time for testing all 255 possible
com ports on Windows?
In my experience both Linux and Windows if you connect a new serial 
device do set a port number just higher than the previous one already there.
This means that you'll have to deal with higher numbers only if you have 
more than 9 serial lines in your platform, which is a bit unlikely. Not 
to consider the likelihood of a platform with 200 serial lines!


--
Do not do to others as you would have them do to you.They might have different 
tastes.

--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Usage of Serial in a testing program?

2018-09-10 Thread Bo Berglund via Lazarus
On Mon, 10 Sep 2018 13:20:35 +0200, Giuliano Colla via Lazarus
 wrote:

>Il 09/09/2018 13:33, Bo Berglund via Lazarus ha scritto:

>>I am writing a testing application for checking out a TCP to Serial
>>bridge component. I am using Lazarus 1.8.0 and fpc 3.0.4 on Windows 7
>>
>>For the serial port handling I found the "built-in" Serial unit
>>described here:
>>http://wiki.freepascal.org/Hardware_Access#FPC_built_in_Serial_unit
>>
>>Now I have a few questions about its usage:
>>
>>1) Serial port name
>>---
>>When opening the port the example does this:
>>
>>str(ComPortNr,tmpstr);
>>ComPortName:= 'COM'+tmpstr+':';
>>serialhandle := SerOpen(ComPortName);
>>
>>So for say port 29 this results in ComPortName 'COM29:'
>>Is this always the case? I have a hunch that for port numbers 1..9 the
>>Windows port naming is different than for higher port numbers...
>>
>>And if I want to port this to Linux, I guess that the name is
>>completely different, but no hint is given.

>Here is the procedure I'm using to fill up a combo box with the
>names of the existing serial devices on the platform. Please note
>the different naming conventions in Linux and Windows. Also note
>that to report a serial port as existing a test is made to open it
>(using the fpc serial function), and avoid "phantom" ports.

But does not this listing fail if a port is already in use, i.e. the
SerOpen() call will return 0 indicating it is not found?

>procedure TForm1.btnScanPortClick(Sender: TObject);
>var
> PortNr: Integer;
> PortName: String;
> PortHandle: TSerialHandle;
>begin
>  cbSelPort.Items.Clear;
>  cbSelPort.Text:= '';
>{$IFDEF MSWINDOWS}
>  for PortNr := 1 to 9 do begin
>PortName := 'COM' + IntToStr(PortNr);
>PortHandle := SerOpen('\\.\'+PortName); //<= Fail if already open?
>if PortHandle  0 then begin
>  cbSelPort.Items.Add(PortName);
>  SerClose(PortHandle);
>  if cbSelPort.Text = '' then begin
>cbSelPort.Text:=PortName;
>PortSel.Caption:= PortName;
>end;
>  end;
>end;
>{$ELSE}
>  for PortNr := 0 to 9 do begin
>PortName := '/dev/ttyS' + IntToStr(PortNr);
>PortHandle := SerOpen(PortName);
>if PortHandle  0 then begin
>  if cbSelPort.Text = '' then begin
>cbSelPort.Text:=PortName;
>PortSel.Caption:= PortName;
>end;
>  cbSelPort.Items.Add(PortName);
>  SerClose(PortHandle);
>  end;
>end;
>  for PortNr := 0 to 9 do begin
>PortName := '/dev/ttyUSB' + IntToStr(PortNr);
>PortHandle := SerOpen(PortName);
>if PortHandle  0 then begin
>  if cbSelPort.Text = '' then begin
>cbSelPort.Text:=PortName;
>PortSel.Caption:= PortName;
>end;
>  cbSelPort.Items.Add(PortName);
>  SerClose(PortHandle);
>  end;
>end;
>{$ENDIF}
>end;

This seems only to deal with ports 1..9, what about the higher
numbered ports 10..255?
And would it not be a long execution time for testing all 255 possible
com ports on Windows?

>>2) Blocking send?
>>--
>>Is this port blocking for sending?
>>
>>The example has this:
>>
>>status := SerWrite(serialhandle, s[1], writecount );
>>
>>where s is a string holding the text to send (I will actually need to
>>use a TBytes array instead) and writecount returns the bytes actually
>>sent.
>>
>>If I want to send an array of say 100 kbytes at 9600 baud, will the
>>call return only when the data have been completely sent or earlier?
>>It will take about 100 seconds to send that array...


>Yes, SerWrite is blocking.

Does this mean that it is actually waiting for the data to be
physically sent out on the wire or until the operating system transmit
buffer has absorbed all of the data?
If the latter then a possibility to resize the transmit buffer would
help. But how?

>I hope you don't plan to send 100 kbytes
>in a single write on a serial line. The probability of an error in
>between is near to 100%!
>What I'm doing in such cases is to create a dedicated thread to
>handle send and receive, without blocking the main thread, which
>remains responsive, and split the send in many small blocks (and
>getting some sort of ACK/NAK from remote receiver), which makes it
>possible to show a progress bar or whatever visual feedback you
>like.

Unfortunately not possible in the real case because the file transfer
protocol of the device only sends a header with the count of the data
to follow and then streams all of the bytes


>>3) Receiving data
>>
>>For data reception I see this:
>>
>>s:='';
>>ComIn:='';
>>while (Length(Comin)10) and (status=0) and not keypressed do 
>>begin
>>   status:= SerRead(serialhandle, s[1], 10);
>>   ...
>>
>>Since the call parameters are the receive buffer and the count to read
>>I do not understand how this can work. s has been emptied (length = 0)
>>just before the call so how can SerRead stuff any data into the buffer
>>starting at s[1], which should not even exist???
>>
>>I would like to have a way to read 

Re: [Lazarus] Usage of Serial in a testing program?

2018-09-10 Thread Mark Morgan Lloyd via Lazarus

On 10/09/18 13:30, Bo Berglund via Lazarus wrote:

On Sun, 9 Sep 2018 20:44:34 +, Mark Morgan Lloyd via 
Lazarus wrote:

I did quite lot of work on the serial.pp unit more recently than that >wiki page, 
in fact I didn't even know it existed. Please refer to the >comments in that file 
in the first instance.

Thanks Mark,I did that too and there is stuff I don't find there, like:
Read blocking?--From interface section:
{ Reads a maximum of "Count" bytes of data into the specified buffer.  Result: 
Number of bytes read. }function SerRead(Handle: TSerialHandle; var Buffer; Count: 
LongInt):LongInt;
Does this function read whatever is in the buffer when called up to amaximum of 
Count, or does it actually wait until Count bytes havearrived? If it waits, for 
how long?


From further down:

function SerRead(Handle: TSerialHandle; var Buffer; Count: LongInt): 
LongInt;

begin
  Result := fpRead(Handle, Buffer, Count);
end;

where the documentation for fpread() says

"FpdRead reads at most nbytes bytes from the file descriptor fd, and 
stores them in buf.


"The function returns the number of bytes actually read"

So this is a unix-style read that is prepared to read  Count  bytes, but 
returns the number actually available.


If you want timeouts then see SerReadTimeout(). I'd expect the Windows 
variants to behave the same (I tested Linux, Solaris and I think W2K, so 
there's a risk that newer versions behave differently). /If/ you find 
anomalies, please raise a bug report with the caveat that I have rather 
a lot of problems on my plate right now.



Concerning the com port name for SerOpen():
{ Open the serial device with the given device name, for example:\COM1, \COM2 
(strictly, \\.\COM1...) for normal serial ports.ISDN devices, serial port 
redirectors/virtualisers etc. normallyimplement names of this form, but refer to your 
OS documentation.  Returns "0" if device could not be found }function 
SerOpen(const DeviceName: String): TSerialHandle;


On Linux that is, again, a very thin wrapper around the RTL fpOpen() 
function, on Windows it's a wrapper around CreateFile(). I really can't 
say the extent that I tested that with odder devices and high port 
numbers (I think I took SerOpen() etc. pretty much as supplied by the 
original author), but from other serial libraries on Delphi my 
recollection is that that leading \\.\ is mandatory for higher-numbered 
ports... I /think/ I got up to 12 ports but that really was a very long 
time ago.


Note that C/C++ examples relating to that sort of thing will usually 
refer to .\\ because of the special significance of \ in strings.



In the Wiki example they use COMx: where x is a number, but this isprobably 
only working for single digit numbers 1..9.In any case the naming there is not 
described in serial.pp
I need to huse a high numbered com port since all I have is USB2Serialdongles, 
which typically get you a port number like 29...


I can't comment on Windows there but on Linux they typically get called 
something like /dev/USB0 etc., with a risk that the numeric suffix will 
increment if it's replugged. I've used that library fairly heavily on 
Linux for instrumentation type stuff, it works fairly well with USB 
devices except that their timing can get flaky if you're trying to get 
the exact time at which e.g. CTS changes state relative to a stream of 
characters faster than about 300 Baud.


When I was working on it the major thing I did was reorganise some of 
the flush/drain/sync stuff which was generally felt to be in a mess, add 
a bit more in the way of control signal interfacing, and add 
SerReadTimeout()... note the provision for an idle callback.


HTH.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Usage of Serial in a testing program?

2018-09-10 Thread Sven Barth via Lazarus
Bo Berglund via Lazarus  schrieb am Mo., 10.
Sep. 2018, 15:19:

> Concerning the com port name for SerOpen():
>
> { Open the serial device with the given device name, for example:
> \COM1, \COM2 (strictly, \\.\COM1...) for normal serial ports.
> ISDN devices, serial port redirectors/virtualisers etc. normally
> implement names of this form, but refer to your OS documentation.
>   Returns "0" if device could not be found }
> function SerOpen(const DeviceName: String): TSerialHandle;
>
> In the Wiki example they use COMx: where x is a number, but this is
> probably only working for single digit numbers 1..9.
> In any case the naming there is not described in serial.pp
>
> I need to huse a high numbered com port since all I have is USB2Serial
> dongles, which typically get you a port number like 29...
>

Did you test it? Cause the serial unit only passes on the name to the
platform's API. So \COM29 should work for a Com port with number 29.

Regards,
Sven

>
-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Usage of Serial in a testing program?

2018-09-10 Thread Bo Berglund via Lazarus
On Sun, 9 Sep 2018 20:44:34 +, Mark Morgan Lloyd via Lazarus
 wrote:

>I did quite lot of work on the serial.pp unit more recently than that 
>wiki page, in fact I didn't even know it existed. Please refer to the 
>comments in that file in the first instance.

Thanks Mark,
I did that too and there is stuff I don't find there, like:

Read blocking?
--
From interface section:

{ Reads a maximum of "Count" bytes of data into the specified buffer.
  Result: Number of bytes read. }
function SerRead(Handle: TSerialHandle; var Buffer; Count: LongInt):
LongInt;

Does this function read whatever is in the buffer when called up to a
maximum of Count, or does it actually wait until Count bytes have
arrived? If it waits, for how long?

Concerning the com port name for SerOpen():

{ Open the serial device with the given device name, for example:
\COM1, \COM2 (strictly, \\.\COM1...) for normal serial ports.
ISDN devices, serial port redirectors/virtualisers etc. normally
implement names of this form, but refer to your OS documentation.
  Returns "0" if device could not be found }
function SerOpen(const DeviceName: String): TSerialHandle;

In the Wiki example they use COMx: where x is a number, but this is
probably only working for single digit numbers 1..9.
In any case the naming there is not described in serial.pp

I need to huse a high numbered com port since all I have is USB2Serial
dongles, which typically get you a port number like 29...


-- 
Bo Berglund
Developer in Sweden

-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Usage of Serial in a testing program?

2018-09-10 Thread Giuliano Colla via Lazarus

  
  
Il 09/09/2018 13:33, Bo Berglund via
  Lazarus ha scritto:


  I am writing a testing application for checking out a TCP to Serial
bridge component. I am using Lazarus 1.8.0 and fpc 3.0.4 on Windows 7

For the serial port handling I found the "built-in" Serial unit
described here:
http://wiki.freepascal.org/Hardware_Access#FPC_built_in_Serial_unit

Now I have a few questions about its usage:

1) Serial port name
---
When opening the port the example does this:

str(ComPortNr,tmpstr);
ComPortName:= 'COM'+tmpstr+':';
serialhandle := SerOpen(ComPortName);

So for say port 29 this results in ComPortName 'COM29:'
Is this always the case? I have a hunch that for port numbers 1..9 the
Windows port naming is different than for higher port numbers...

And if I want to port this to Linux, I guess thta the name is
completely different, but no hint is given.


Here is the procedure I'm using to fill up a combo box with the
names of the existing serial devices on the platform. Please note
the different naming conventions in Linux and Windows. Also note
that to report a serial port as existing a test is made to open it
(using the fpc serial function), and avoid "phantom" ports.
procedure TForm1.btnScanPortClick(Sender: TObject);
var
 PortNr: Integer;
 PortName: String;
 PortHandle: TSerialHandle;
begin
  cbSelPort.Items.Clear;
  cbSelPort.Text:= '';
{$IFDEF MSWINDOWS}
  for PortNr := 1 to 9 do begin
PortName := 'COM' + IntToStr(PortNr);
PortHandle := SerOpen('\\.\'+PortName);
if PortHandle > 0 then begin
  cbSelPort.Items.Add(PortName);
  SerClose(PortHandle);
  if cbSelPort.Text = '' then begin
cbSelPort.Text:=PortName;
PortSel.Caption:= PortName;
end;
  end;
end;
{$ELSE}
  for PortNr := 0 to 9 do begin
PortName := '/dev/ttyS' + IntToStr(PortNr);
PortHandle := SerOpen(PortName);
if PortHandle > 0 then begin
  if cbSelPort.Text = '' then begin
cbSelPort.Text:=PortName;
PortSel.Caption:= PortName;
end;
  cbSelPort.Items.Add(PortName);
  SerClose(PortHandle);
  end;
end;
  for PortNr := 0 to 9 do begin
PortName := '/dev/ttyUSB' + IntToStr(PortNr);
PortHandle := SerOpen(PortName);
if PortHandle > 0 then begin
  if cbSelPort.Text = '' then begin
cbSelPort.Text:=PortName;
PortSel.Caption:= PortName;
end;
  cbSelPort.Items.Add(PortName);
  SerClose(PortHandle);
  end;
end;
{$ENDIF}
end;



  
2) Blocking send?
--
Is this port blocking for sending?

The example has this:

status := SerWrite(serialhandle, s[1], writecount );

where s is a string holding the text to send (I will actually need to
use a TBytes array instead) and writecount returns the bytes actually
sent.

If I want to send an array of say 100 kbytes at 9600 baud, will the
call return only when the data have been completely sent or earlier?
It will take about 100 seconds to send that array...


Yes, SerWrite is blocking. I hope you don't plan to send 100 kbytes
in a single write on a serial line. The probability of an error in
between is near to 100%!
What I'm doing in such cases is to create a dedicated thread to
handle send and receive, without blocking the main thread, which
remains responsive, and split the send in many small blocks (and
getting some sort of ACK/NAK from remote receiver), which makes it
possible to show a progress bar or whatever visual feedback you
like.

  
3) Receiving data

For data reception I see this:

s:='';
ComIn:='';
while (Length(Comin)<10) and (status>=0) and not keypressed do 
begin
   status:= SerRead(serialhandle, s[1], 10);
   ...

Since the call parameters are the receive buffer and the count to read
I do not understand how this can work. s has been emptied (length = 0)
just before the call so how can SerRead stuff any data into the buffer
starting at s[1], which should not even exist???

I would like to have a way to read incoming data asynchronously so I
also could handle the user feedback and the TCP connection which is
sending the data that ultimately will arrive on the serial line...

Any suggestions on how to do this?




I never use SerRead, but rather SerReadTimeout (from the same
  unit) which gives a much better control of what is going on. Of
  course in that case your receiving buffer must be large enough to
  accommodate the largest block you expect. (This replies also to
  your further questions).



I hope that it helps.


Giuliano

-- 
Do not do to others as you would have them do to you.They might have different tastes.

  

-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus