Recent

Author Topic: TLazSerial : serial port component for Lazarus (windows and linux).  (Read 393388 times)

CM630

  • Hero Member
  • *****
  • Posts: 1548
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #480 on: June 06, 2025, 10:06:26 am »
I tried in a VirtualMachine (maybe that matters). I guess the Linux distro doesn not matter (since bugs in Mount are present in Android too).
1. Sometimes executing GetSerialPortNames takes 5,5 seconds, usually it is much-much faster.

The trouble is the file won't disappear while it is open.
 
Try
Code: Pascal  [Select][+][-]
  1. if FpStat(FileName, Sta) = 0 then
  2.       if Sta.st_ctime = 0 then {disconnected};

Actually the /dev/ttyUSB* does disappear even when the serial connection is active.
I tried both your solution and if fileexists and both solutions seem to do what is necessary.



Still, there is something odd:
Without this line if (pluggedin = False) and (LazSerial1.Active)  then begin LazSerial1.Active := False; CheckBox1.Checked := false end; the Memo1 stops updating when the device is unplugged, while LazSerial1.Active = True?!

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
  9.   LazSerial, LazSynaSer,BaseUnix;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     CheckBox1: TCheckBox;
  17.     LazSerial1: TLazSerial;
  18.     Memo1: TMemo;
  19.     Timer1: TTimer;
  20.     procedure CheckBox1Change(Sender: TObject);
  21.     procedure FormCreate(Sender: TObject);
  22.     procedure Timer1Timer(Sender: TObject);
  23.   private
  24.  
  25.   public
  26.  
  27.   end;
  28.  
  29. var
  30.   Form1: TForm1;
  31.   firsttick : QWord;
  32.   Device : string = '/dev/ttyUSB0';
  33.  
  34. implementation
  35.  
  36. {$R *.lfm}
  37.  
  38. { TForm1 }
  39.  
  40. procedure TForm1.Timer1Timer(Sender: TObject);
  41. var
  42.   pluggedin: Boolean = False;
  43.   Sta: Stat;
  44. begin
  45.   {if FpStat(Device, Sta) = 0 then
  46.     pluggedin := not (Sta.st_ctime = 0);}
  47.   pluggedin := FileExists(Device);
  48.  
  49.   if (pluggedin = False) and (LazSerial1.Active)  then begin LazSerial1.Active := False; CheckBox1.Checked := false end;
  50.    memo1.Append (IntToStr(GetTickCount64-firsttick) + ' ' + Device + ' ' + BoolToStr(  pluggedin, 'Plugged in', 'Unplugged'));
  51.   memo1.SelStart := MaxInt;
  52.   Application.ProcessMessages;
  53. end;
  54.  
  55. procedure TForm1.FormCreate(Sender: TObject);
  56. begin
  57.    firsttick := GetTickCount64;
  58.    LazSerial1.Device := Device;
  59. end;
  60.  
  61. procedure TForm1.CheckBox1Change(Sender: TObject);
  62. begin
  63.   LazSerial1.Active := CheckBox1.Checked;
  64. end;
  65.  
  66. end.

Still, I have not tried the other proposals.
« Last Edit: June 06, 2025, 10:11:23 am by CM630 »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

alpine

  • Hero Member
  • *****
  • Posts: 1410
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #481 on: June 06, 2025, 10:38:45 am »
Quote
Actually the /dev/ttyUSB* does disappear even when the serial connection is active.
I tried both your solution and if fileexists and both solutions seem to do what is necessary.
Every time you unplug and then plug back the pigtail, a new ttyUSB* appears with a different number. That's why I'm making links into the udevadm configuration - to have always a single file name to rely on.


"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

MarkMLl

  • Hero Member
  • *****
  • Posts: 8515
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #482 on: June 06, 2025, 11:25:04 am »
Quote
Actually the /dev/ttyUSB* does disappear even when the serial connection is active.
I tried both your solution and if fileexists and both solutions seem to do what is necessary.
Every time you unplug and then plug back the pigtail, a new ttyUSB* appears with a different number. That's why I'm making links into the udevadm configuration - to have always a single file name to rely on.

I don't see that. There are definitely changes in internal naming, but at the /dev/ttyUSBx level allocation is monotonic without gaps... although that could potentially go wrong if a device was removed and reinserted rapidly, or if there was a hardware error which glitched the hotplugging events.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

CM630

  • Hero Member
  • *****
  • Posts: 1548
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #483 on: June 06, 2025, 12:25:37 pm »
What I observe in the virtualbox is that devices are added in order of appearance.
The first one connected becomes /dev/ttyUSB0, the second one is /dev/ttyUSB1...
So when I unplug device /ttyUSB0 and connect another device, the new one becomes /ttyUSB0.

For comparison, Windows dedicates a separate COM number for each device.

So if the idea is to recover a connection after a device was lost and reconnected (might happen due to USB hub issues, for example), instead of editing
/etc/udevadm/rules.d/99-local.rules on every particular PC, it might be better to retrieve the data (PID_VID and serial number) and then search the new device by these values. I have not searched how to get these values, my idea was to show a message "Connection lost" and to set the app in inactive state.

Edit: I suppose it is not possible to distinguish one CH340 device from another, they do not seem to have serial numbers.
« Last Edit: June 06, 2025, 12:37:48 pm by CM630 »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

MarkMLl

  • Hero Member
  • *****
  • Posts: 8515
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #484 on: June 06, 2025, 12:52:46 pm »
OK, so it's a virtualisation issue; I almost updated my comment to blame systemd or something quirky about udev.

The serial number can be read from the /sys tree (or potentially from lsusb etc. output), but while genuine FTDI converters contain a usable one just about everything else either has nothing or has it hardwired to a fixed value... and that's particularly the case for counterfeit FTDIs:

Code: Pascal  [Select][+][-]
  1.   descriptionTemplate: TPortDescription= (
  2.                          baseName: 'ttyUSB';
  3.                          idVendor: '';
  4.                          idProduct: '';
  5.                          busType: '';
  6.                          driverName: 'usb-serial/drivers/ftdi_sio';
  7.                          manufacturer: ''; (* Avoid: varies on counterfeits etc. *)
  8.                          product: 'FT232R USB UART';
  9.                          serial: 'A50285BI' (* Common in counterfeit R/O EEPROM *)
  10.                        );
  11.  

https://github.com/MarkMLl/serialcomms/blob/main/locateftdiport.pas

The ftdi_eeprom program can write a serial number to genuine chips, but not counterfeits. I suspect that counterfeits were writable pre-2014, which is how FTDI's driver on Windows was able to screw with the VID.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

CM630

  • Hero Member
  • *****
  • Posts: 1548
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #485 on: November 06, 2025, 12:21:27 pm »
@JurassicPork, would you like to add some updates to TLazSerial once (if) they are ready, otherwise I will upload them somewhere else, local copies are not always the best storage.

Currently, the main problem is that with the updated component, sometimes Lazarus disappears without a sign, together with the running app. No error, no exception, nothing?!
The other issue is with friendly names in Windows - they are retrieved from the registry, but Windows keeps a mess there, probably some Windows API shall be used for more reliable results.
This is also valid for GetSerialPortNames (I have not touched it for Windows) from LazSynaSer - it retrieves the data from HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM\, but the COM port might not be added (or removed from) there.

Info for any unlisted VID_PIDs of serial devices are welcome, here is what I have for now:
vid_0403&pid_6001 : SerialFTDI
vid_1a86&pid_7523 : SerialCH340
vid_067b&pid_2303 : SerialProlific
vid_0483&pid_5740 : SerialSTM
vid_2341&pid_8036 : SerialArduinoLeonardo
vid_10c4&pid_ea60 : SiliconLabsCP210x
vid_2184&pid_0040 : GwInstek
btbt              : BluetoothSerial 


Otherwise, here is the list of the changes:

1. LazSerial
  1.1. Event .OnDisconnected added. Triggers if the serial device is unplugged (uninstalled or dismounted...) while being connected.

2. lazsynaser.pas
Some things added for MacOs, it did not seem to work (much), hopefuly now it is a little better.
Not clear: Some items are listed in /dev both with prefix /dev/tty.usb* and /dev/cu.usb*. Shall it tty stay? Maybe only for some (older) versions of MacOS.
There is ssoHide_tty_usbserial in the options of SerialSelector (enabled by the default.)

3. SerialWatcher - new unit. Keeps an eye on the serial devices and sends an event if a device is plugged or unplugged.
      (OnComConnected and OnComDisconnected, I wonder if I should rename them).
I think it does not work on MacOs.

4. SerialSelector - new component, a combobox for selecting serial ports.
  4.1. It updates its content whenever a device is plugged / unplugged.
  4.2. If enabled, it shows friendly names of the COM ports, which is useful when multiple serial devices are connected to the computer.
  4.3. It shows in a hint the last connected /disconnected devices and the friendly name of the selected port.

5. Known bugs:
  5.1. Windows
    5.1.1. Sometimes Lazarus disappears without a sign, together with the running app. No error, no exception, nothing?! (happened at least twice)
  5.2. Linux
    5.2.1. The added devices are not listed in the hints - Fixed in 2025.11.07.
    5.2.2. The hints show when a device is (dis)connected, even if the mouse is not over the control. Fixed in 2025.11.08 (not yet uploaded)
    5.2.3. The hint does not hide sometimes. Fixed in 2025.11.08 (not yet uploaded)
  5.3. MacOS
    5.3.1. Removing devices does not seem to be detected: Possibly fixed in in 2025.11.07.
    5.3.2. Some errors are shown while building, but trying to run a couple of times makes the sample app work. Probably something with Lazarus.
    5.3.3. Some Cocoa errors are shown, the app crashes. No idea if is Lazarus to blame or TLazSerial, it seems to happen when trying to add text to a TMemo.
    5.3.4. Friendly names are not shown, not implemented, and probably will never be.
  5.4. Common: Cannot set the height

There is an example project inside, folder test1.

     
« Last Edit: November 10, 2025, 03:26:43 pm by CM630 »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

tetrastes

  • Hero Member
  • *****
  • Posts: 706
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #486 on: November 06, 2025, 04:14:46 pm »
Info for any unlisted VID_PIDs of serial devices are welcome, here is what I have for now:

http://www.linux-usb.org/usb.ids  :D

mas steindorff

  • Hero Member
  • *****
  • Posts: 560
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #487 on: November 06, 2025, 07:03:25 pm »

5. Known bugs:
  5.1. Windows
    5.1.1. Sometimes Lazarus disappears without a sign, together with the running app. No error, no exception, nothing?! (happened at least twice)

Hi CM630, Which windows are you testing on?  for Win10, the driver can kill the client.  When the driver locks up, windows can kill it and restart which can take out the thread you used to connect with.  I have more success keeping the serial in a separate thread that can be closed and reopened as needed.  static discharge on the COM port / VCP hardware will mess the driver.

Lately the driver dies and will not reload until I close the port. this is usually due to me debugging/restarting the VCP device. What I do is to PING the device if nothing received in 3 to 5 seconds and will cycle the port on failure. I found I need to Close and reopen at different intervals with up to 5 second down time so the driver will reload/restart.  this also works for Bluetooth in and out of range issues.
My code/exe works on Win11 but I have not tested it as hard with static zaps yet.
MAS
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

CM630

  • Hero Member
  • *****
  • Posts: 1548
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #488 on: November 07, 2025, 01:45:15 pm »
I have attached the code with some fixes, mostly for Linux.


5. Known bugs:
  5.1. Windows
    5.1.1. Sometimes Lazarus disappears without a sign, together with the running app. No error, no exception, nothing?! (happened at least twice)

Hi CM630, Which windows are you testing on?  for Win10, the driver can kill the client.  When the driver locks up, windows can kill it and restart which can take out the thread you used to connect with.  I have more success keeping the serial in a separate thread that can be closed and reopened as needed.  static discharge on the COM port / VCP hardware will mess the driver.

Lately the driver dies and will not reload until I close the port. this is usually due to me debugging/restarting the VCP device. What I do is to PING the device if nothing received in 3 to 5 seconds and will cycle the port on failure. I found I need to Close and reopen at different intervals with up to 5 second down time so the driver will reload/restart.  this also works for Bluetooth in and out of range issues.
My code/exe works on Win11 but I have not tested it as hard with static zaps yet.
MAS
We switched from Win 10 to Win11 a few weeks ago. AFAIR I have never seen Lazarus disappear before, at least not ot Windows, but the control did not exist then.
Today Lazarus disappeared again when I unplugged a device and the sample app was running, but there was no active serial connection, just the app watching the registry and updating the indication. So I assume it is not a driver issue.


http://www.linux-usb.org/usb.ids  :D
Thanks, really a useful resource.


Edit: Added v2025.11.08 - fix for the Hint in Lazarus.
Edit: 2025.11.18 - Device is now writeable, when set the item index is changed if the provided value is present in the list.
« Last Edit: November 18, 2025, 01:35:07 pm by CM630 »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1269
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #489 on: November 30, 2025, 09:23:43 am »
Got some questions:  This seems like the correct thread, but let me know if you want me to create a new thread...

I'd like to introduce a patch that sorts the com ports naturally (COM3, COM4, COM10, COM11, COM20, COM21) in the Serial Port config dialog (Before you ask, I'm using com0com to add some virtual bridged com ports, and bridging COM10-COM20, COM11-COM21 is helping me keep things straight in my head).

I've got the code working on Windows.  Uses RTL.StrUtls.NaturalCompareText.

Before I generate the patch: 

Looks to me like NaturalCompareText was introduced to FPC in 3.0.2, so I'll wrap my code in {$IF FPC_FULLVERSION >= 30002}.  Outside of that, I'll sort the COM Ports alphabetically.

Is https://github.com/JurassicPork/TLazSerial still the correct repository?    Not sure how onlinepackagerepository works.

I'm a Windows user in this context.  No idea what com ports look like on Linux or Macs.  Will a natural sort order make sense?  Should I instead sort alphabetically?  Or does the existing sort order in Linux make structural sense and I'm better off leaving that alone?

Many thanks

Mike

Lazarus Trunk/FPC latest fixes on Windows 11
  I'm getting old and stale.  Slowly getting used to git, I'll get there...

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1269
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #490 on: November 30, 2025, 09:34:40 am »
I have attached the code with some fixes, mostly for Linux.

Interesting.  I'll download your code and have a look.  If I understand this from a quick scan, we're playing in similar grounds (the name of things). 

Once I know the correct repository, if you like I can either create a patch for you, or submit a pull request on your behalf?

Update:
You've got a file in there: NewSerialSelector.pas.  Does nothing but add .AppendFriendlyNames property to a TCustomComboBox
If you meant to include this file, then I'd suggest there's no need for the register there.  That places the component in IDE, and I can't see other users would get a use of this component as it currently stands.

However, I suyspect NewSerialSelector.pas was an accidental inclusion, given that SerialSelector.pas has what appears to be a fully implemented Combobox.
« Last Edit: November 30, 2025, 10:33:40 am by Mike.Cornflake »
Lazarus Trunk/FPC latest fixes on Windows 11
  I'm getting old and stale.  Slowly getting used to git, I'll get there...

CM630

  • Hero Member
  • *****
  • Posts: 1548
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #491 on: November 30, 2025, 11:24:31 am »
Thanks, I will check what NewSerialSelector.pas is.
Meanwhile I have made some changes, not uploaded yet, because they need some cleaning.
I added one more component - SerialWatcher (was only a .pas in the last uploaded release).

The current implementation sorts the names of the COM ports, but if you post the code using native component (RTL.StrUtls.NaturalCompareText  if I have understood you right), maybe it can be reused.

« Last Edit: November 30, 2025, 11:37:06 am by CM630 »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1269
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #492 on: November 30, 2025, 11:36:27 am »
The current implementation sorts the names of the COM ports, but if you post the code using native component (RTL.StrUtls.NaturalCompareText  if I have understood you right), maybe it can be reused.

By stripping the prefixes - your sort is possibly already natural sort.  At the moment I'm still reading code, haven't run anything.

My code is based on the old TComboBox.  You've replaced that, so more thought on my behalf is required.

Here's my code.  Not yet sanitised for FPC Ver, and I haven't done anything with Linux code yet either. 

This is all in LazSynaSer.pas...   

Just above GetSerialPortNames...

Code: Pascal  [Select][+][-]
  1. function NaturalSortCompare(List: TStringList; Index1, Index2: Integer): Integer;
  2. begin
  3.   Result := NaturalCompareText(List[Index1], List[Index2]);
  4. end;  
  5.  

Then in GetSerialPortNames...

Code: Pascal  [Select][+][-]
  1. ...
  2.     v.CustomSort(@NaturalSortCompare);  
  3. ...
  4.  
Lazarus Trunk/FPC latest fixes on Windows 11
  I'm getting old and stale.  Slowly getting used to git, I'll get there...

CM630

  • Hero Member
  • *****
  • Posts: 1548
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #493 on: November 30, 2025, 11:38:11 am »
I will need time to comprehend you code. Meanwhile:

I'm a Windows user in this context.  No idea what com ports look like on Linux or Macs.  Will a natural sort order make sense?  Should I instead sort alphabetically?  Or does the existing sort order in Linux make structural sense and I'm better off leaving that alone?
In Linux and MacOs they are filenames, so it seems reasonable to sort them.
Besides that, in MacOs there seems to be two “files” per serial port, only one of which seems usable... not sure, that is how it seems to work.

I do not rememeber if sorting in Linux works, I will check the in the next days.
« Last Edit: November 30, 2025, 11:41:52 am by CM630 »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1269
Re: TLazSerial : serial port component for Lazarus (windows and linux).
« Reply #494 on: November 30, 2025, 11:52:57 am »
Here's a fuller copy of the code:  (Need to add Strutils to Uses)

Code: Pascal  [Select][+][-]
  1. {$IFDEF MSWINDOWS}
  2. function NaturalSortCompare(List: TStringList; Index1, Index2: Integer): Integer;
  3. begin
  4.   Result := NaturalCompareText(List[Index1], List[Index2]);
  5. end;
  6.  
  7. function GetSerialPortNames: string;
  8. var
  9.   reg: TRegistry;
  10.   l, v: TStringList;
  11.   n: integer;
  12. begin
  13.   l := TStringList.Create;
  14.   v := TStringList.Create;
  15.   reg := TRegistry.Create;
  16.  
  17.   try
  18. {$IFNDEF VER100}
  19. {$IFNDEF VER120}
  20.     reg.Access := KEY_READ;
  21. {$ENDIF}
  22. {$ENDIF}
  23.     reg.RootKey := HKEY_LOCAL_MACHINE;
  24.     reg.OpenKey('\HARDWARE\DEVICEMAP\SERIALCOMM\', false);
  25.     reg.GetValueNames(l);
  26.     for n := 0 to l.Count - 1 do
  27. // Modif J.P  03/2013
  28.       v.Add(Pchar(reg.ReadString(l[n])));
  29.     v.CustomSort(@NaturalSortCompare);
  30.     Result := v.CommaText ;
  31.   finally
  32.     reg.Free;
  33.     l.Free;
  34.     v.Free;
  35.   end;
  36. end;
  37.  
Lazarus Trunk/FPC latest fixes on Windows 11
  I'm getting old and stale.  Slowly getting used to git, I'll get there...

 

TinyPortal © 2005-2018