Lazarus

Programming => Operating Systems => Linux => Topic started by: af0815 on January 16, 2019, 09:23:06 pm

Title: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: af0815 on January 16, 2019, 09:23:06 pm
I want to detect the actual IP of the Ethernetport. Only the local IP on a RasPi with (actual) Raspbian. Is this possible to to with Pascal or only with a cmdline Tool and parsing the output ?

I have searched, but the found soloutions are only for an extrenal IP or not working on a RasPi with Rasbian.



Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: sash on January 18, 2019, 11:39:28 pm
What exactly doesn't work?

Also, what do you mean by "local IP", loopback interface address?
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: af0815 on January 19, 2019, 11:39:05 am
A RasPi have one Ethernetport with an IP adress and one wlan adapter with one IP adress. Both are default DHCP. I want to query the actual local IP. Specially for Ethernet, but if i get both/all with an indication what device is used, it is ok and i can filter out the loopback.
This should work with static IP too. Because i didnt know how the RasPi is configured and installed. And the detection should work with out root privileges (no sudo).

Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: HeavyUser on January 19, 2019, 01:17:23 pm
I want to detect the actual IP of the Ethernetport. Only the local IP on a RasPi with (actual) Raspbian. Is this possible to to with Pascal or only with a cmdline Tool and parsing the output ?

I have searched, but the found soloutions are only for an extrenal IP or not working on a RasPi with Rasbian.
using indy 10 its as simple as
Code: Pascal  [Select]
  1.  
  2. uses  IdStack;
  3.  
  4. procedure TForm1.btnRetreiveIPsClick(Sender :TObject);
  5. begin
  6.   TIdStack.IncUsage;
  7.   try
  8.     GStack.AddLocalAddressesToList(ListBox1.Items);
  9.   finally
  10.     TIdStack.DecUsage;
  11.   end;
  12. end;                      
  13.  

PS.
Listbox1.items can be replaced with any TStringlist variable with out any other changes. eg

Code: Pascal  [Select]
  1. Function RetreiveIPs(Sender :TObject):TStringList;
  2. begin
  3.   Result := TStringList.Create;
  4.   try
  5.     TIdStack.IncUsage;
  6.     try
  7.       GStack.AddLocalAddressesToList(Result);
  8.     finally
  9.       TIdStack.DecUsage;
  10.     end;
  11.   Except
  12.       On E:Exception do begin
  13.         Result.free; //no memory leaks please.
  14.         Raise E;
  15.      end;
  16.   end;
  17. end;                      
  18.  
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: af0815 on January 19, 2019, 01:32:53 pm
Thx for the sample, BUT indy is realy too oversized for querying only the IP =:-)

I have tried this:

Code: Pascal  [Select]
  1. function GetIPAddress: string;
  2. var
  3.   theProcess: TProcess;
  4.   AddressString: AnsiString;
  5. begin
  6.   try
  7.     theProcess := TProcess.Create(nil);
  8.     theProcess.Executable := 'hostname';
  9.     theProcess.Parameters.Add('-I');
  10.     theProcess.Options := [poUsePipes];
  11.     theProcess.Execute;
  12.     if theProcess.Output.NumBytesAvailable > 0 then
  13.     begin
  14.       SetLength(AddressString{%H-}, theProcess.Output.NumBytesAvailable);
  15.       theProcess.Output.ReadBuffer(AddressString[1], theProcess.Output.NumBytesAvailable);
  16.     end;
  17.     GetIPAddress := AddressString;
  18.   finally
  19.     theProcess.Free;
  20.   end;
  21. end;
  22.  
But i got no response. hostname on commandline works. If i work with the debugger now on a RasPi, i see it is working sometimes. I dig deeper and found, i have to use
Code: Pascal  [Select]
  1. heProcess.Options := [poUsePipes,poWaitOnExit];
Now i got a response. I have to test more.

A second improvement maybe
Code: Pascal  [Select]
  1. theProcess.Parameters.Add('--all-ip-addresses');
If i read the manuals correct.




 
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: HeavyUser on January 19, 2019, 01:42:59 pm
Thx for the sample, BUT indy is realy too oversized for querying only the IP =:-)

You do understand that the installation size and your applications size are two different things right? In this case it should only add minimal size in the KB range in your exe.

Having said that I will not search through the code of the library for you.

I have tried this:

Code: Pascal  [Select]
  1. function GetIPAddress: string;
  2. var
  3.   theProcess: TProcess;
  4.   AddressString: AnsiString;
  5. begin
  6.   try
  7.     theProcess := TProcess.Create(nil);
  8.     theProcess.Executable := 'hostname';
  9.     theProcess.Parameters.Add('-I');
  10.     theProcess.Options := [poUsePipes];
  11.     theProcess.Execute;
  12.     if theProcess.Output.NumBytesAvailable > 0 then
  13.     begin
  14.       SetLength(AddressString{%H-}, theProcess.Output.NumBytesAvailable);
  15.       theProcess.Output.ReadBuffer(AddressString[1], theProcess.Output.NumBytesAvailable);
  16.     end;
  17.     GetIPAddress := AddressString;
  18.   finally
  19.     theProcess.Free;
  20.   end;
  21. end;
  22.  
But i got no response. hostname on commandline works. If i work with the debugger now on a RasPi, i see it is working sometimes. I dig deeper and found, i have to use
Code: Pascal  [Select]
  1. heProcess.Options := [poUsePipes,poWaitOnExit];
Now i got a response. I have to test more.

A second improvement maybe
Code: Pascal  [Select]
  1. theProcess.Parameters.Add('--all-ip-addresses');
If i read the manuals correct.

Sorry I never execute external application from code unless the user has request it (eg open a document or an URL) its a chip trick that has nothing to do with programming its only useful for system admins and scripters.
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: Thaddy on January 19, 2019, 02:12:27 pm
Synapse has a function called GetLocalIPs and that works on a Raspberry Pi (any version).
It is in the BlckSock unit. http://synapse.ararat.cz/doc/help/
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: engkin on January 19, 2019, 03:39:01 pm
One simple solution involves a connection using TInetSocket:
Code: Pascal  [Select]
  1. program project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  7.   cthreads,
  8.   {$ENDIF}{$ENDIF}
  9.   sockets, ssockets;
  10.  
  11. var
  12.   c: TInetSocket;
  13. begin
  14.   //catch ESocketError (seHostNotFound or seConnectFailed) if you care
  15.   try
  16.     c := TInetSocket.Create('www.google.com',80);
  17.     WriteLn(NetAddrToStr(c.LocalAddress.sin_addr));
  18.   finally
  19.     c.Free;
  20.   end;
  21.   ReadLn;
  22. end.

A better solution I found linked on SO is here (http://www.geekpage.jp/en/programming/linux-network/get-ipaddr.php):
Code: C  [Select]
  1. #include <stdio.h>
  2. #include <string.h> /* for strncpy */
  3. #include <sys/types.h>
  4. #include <sys/socket.h>
  5. #include <sys/ioctl.h>
  6. #include <netinet/in.h>
  7. #include <net/if.h>
  8. int
  9. main()
  10. {
  11.  int fd;
  12.  struct ifreq ifr;
  13.  fd = socket(AF_INET, SOCK_DGRAM, 0);
  14.  /* I want to get an IPv4 IP address */
  15.  ifr.ifr_addr.sa_family = AF_INET;
  16.  /* I want IP address attached to "eth0" */
  17.  strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);
  18.  ioctl(fd, SIOCGIFADDR, &ifr);
  19.  close(fd);
  20.  /* display result */
  21.  printf("%s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
  22.  return 0;
  23. }

Unfortunately I failed to convert to Pascal.
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: af0815 on January 19, 2019, 04:39:40 pm
Synapse has a function called GetLocalIPs and that works on a Raspberry Pi (any version).
It is in the BlckSock unit. http://synapse.ararat.cz/doc/help/
You know, synaser have a nasty bug and cannot compile an a RasPi without changing the sources.
 
Quote
Compile package laz_synapse 40.1: Exit code 1, Errors: 22, Warnings: 26, Hints: 91
....
synaser.pas(232,15) Error: Identifier not found "B500000"
synaser.pas(232,22) Error: Illegal expression
synaser.pas(233,14) Error: Identifier not found "B576000"
synaser.pas(233,21) Error: Illegal expression
synaser.pas(234,14) Error: Identifier not found "B921600"
synaser.pas(234,21) Error: Illegal expression
synaser.pas(235,15) Error: Identifier not found "B1000000"
synaser.pas(235,23) Error: Illegal expression
synaser.pas(236,15) Error: Identifier not found "B1152000"
synaser.pas(236,23) Error: Illegal expression
synaser.pas(237,15) Error: Identifier not found "B1500000"
synaser.pas(237,23) Error: Illegal expression
synaser.pas(238,15) Error: Identifier not found "B2000000"
synaser.pas(238,23) Error: Illegal expression
synaser.pas(239,15) Error: Identifier not found "B2500000"
synaser.pas(239,23) Error: Illegal expression
synaser.pas(240,15) Error: Identifier not found "B3000000"
synaser.pas(240,23) Error: Illegal expression
synaser.pas(241,15) Error: Identifier not found "B3500000"
synaser.pas(241,23) Error: Illegal expression
synaser.pas(242,15) Error: Identifier not found "B4000000"
synaser.pas(242,23) Error: Illegal expression
I think this is a missing definition in fpc (missed in termios.inc) or not handled by synapse. So it is not working on arm
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: af0815 on January 19, 2019, 04:52:56 pm
Synapse has a function called GetLocalIPs
The function is in synamisc not blcksock and is not working correct - only return localhost

Quote
--- GetIPAddress (with hostname)---
192.168.1.41
--- GetIpAddrList (with ifconfig)---
192.168.1.41  127.0.0.1 
--- Synase GetLocalIPs ---
127.0.1.1
I have tested it with hostname, ifconfig and synapse DIRECT on a Raspi

Quote
uname -a
Linux XxxPi 4.14.71-v7+ #1145 SMP Fri Sep 21 15:38:35 BST 2018 armv7l GNU/Linux


Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: af0815 on January 19, 2019, 05:07:49 pm
One simple solution involves a connection using TInetSocket:

It is working :-) THX for this 'not scriptkidding' woking soloution.
Quote
--- GetIpAddrList (with TInetSocket)---
192.168.1.41

Edit: Attached the testproject
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: engkin on January 19, 2019, 05:24:10 pm
A cleaner solution should not involve a connection. There is another thread (http://forum.lazarus.freepascal.org/index.php/topic,30062.0.html) that uses getifaddrs
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: avra on January 20, 2019, 03:26:39 am
You know, synaser have a nasty bug and cannot compile an a RasPi without changing the sources.
 
Quote
Compile package laz_synapse 40.1: Exit code 1, Errors: 22, Warnings: 26, Hints: 91
....
synaser.pas(232,15) Error: Identifier not found "B500000"
synaser.pas(232,22) Error: Illegal expression
synaser.pas(233,14) Error: Identifier not found "B576000"
synaser.pas(233,21) Error: Illegal expression
synaser.pas(234,14) Error: Identifier not found "B921600"
synaser.pas(234,21) Error: Illegal expression
synaser.pas(235,15) Error: Identifier not found "B1000000"
synaser.pas(235,23) Error: Illegal expression
synaser.pas(236,15) Error: Identifier not found "B1152000"
synaser.pas(236,23) Error: Illegal expression
synaser.pas(237,15) Error: Identifier not found "B1500000"
synaser.pas(237,23) Error: Illegal expression
synaser.pas(238,15) Error: Identifier not found "B2000000"
synaser.pas(238,23) Error: Illegal expression
synaser.pas(239,15) Error: Identifier not found "B2500000"
synaser.pas(239,23) Error: Illegal expression
synaser.pas(240,15) Error: Identifier not found "B3000000"
synaser.pas(240,23) Error: Illegal expression
synaser.pas(241,15) Error: Identifier not found "B3500000"
synaser.pas(241,23) Error: Illegal expression
synaser.pas(242,15) Error: Identifier not found "B4000000"
synaser.pas(242,23) Error: Illegal expression
I think this is a missing definition in fpc (missed in termios.inc) or not handled by synapse. So it is not working on arm

Are you using official Synapse with Synaser? It is old and you should use OPM's version or trunk. In OPM's version I can see this:

Code: Pascal  [Select]
  1. const
  2. {$IFDEF UNIX}
  3.   {$IFDEF BSD}
  4.   MaxRates = 18;  //MAC
  5.   {$ELSE}
  6.    MaxRates = 30; //UNIX
  7.   {$ENDIF}
  8. {$ELSE}
  9.   MaxRates = 19;  //WIN
  10. {$ENDIF}
  11.   Rates: array[0..MaxRates, 0..1] of cardinal =
  12.   (
  13.     (0, B0),
  14.     (50, B50),
  15.     (75, B75),
  16.     (110, B110),
  17.     (134, B134),
  18.     (150, B150),
  19.     (200, B200),
  20.     (300, B300),
  21.     (600, B600),
  22.     (1200, B1200),
  23.     (1800, B1800),
  24.     (2400, B2400),
  25.     (4800, B4800),
  26.     (9600, B9600),
  27.     (19200, B19200),
  28.     (38400, B38400),
  29.     (57600, B57600),
  30.     (115200, B115200),
  31.     (230400, B230400)
  32. {$IFNDEF BSD}
  33.     ,(460800, B460800)
  34.   {$IFDEF UNIX}
  35.     ,(500000, B500000),
  36.     (576000, B576000),
  37.     (921600, B921600),
  38.     (1000000, B1000000),
  39.     (1152000, B1152000),
  40.     (1500000, B1500000),
  41.     (2000000, B2000000),
  42.     (2500000, B2500000),
  43.     (3000000, B3000000),
  44.     (3500000, B3500000),
  45.     (4000000, B4000000)
  46.   {$ENDIF}
  47. {$ENDIF}
  48.     );
  49. {$ENDIF}
  50.  

So B500000 and others should be defined.
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: af0815 on January 20, 2019, 08:25:54 am
Its OPM Version. B500000 and the other not defined in termios.inc as i sayed before. Maybe the arm cannot handle this. So it should fixed. Is fpc team responsible or Synapse ?

But Synapse didnt send back the correct answer as i stated before.
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: avra on January 20, 2019, 02:23:37 pm
Its OPM Version. B500000 and the other not defined in termios.inc as i sayed before. Maybe the arm cannot handle this. So it should fixed. Is fpc team responsible or Synapse ?
You are right. I have just compared termios.inc from 3.0.5 and 3.2.1 (3.2.1 from December).  Although difference is huge, some things are missing. \fpcsrc\rtl\linux\termios.inc from 3.0.5 has only {$ifdef cpuarm} with baudrates up to B460800, and 3.2.1 has the same defines for cpuarm (up to B460800), but it also has {$ifdef cpuaarch64} with defines up to B4000000. So I would say that currently B500000..B4000000 is currently possible on cpuaarch64 and not on cpuarm. Therefore I guess that you are trying to use cpuarm. You might try to extend cpuarm version and test if it eventualy works.
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: Thaddy on January 20, 2019, 02:36:41 pm
I thought this was already fixed.....(because I fixed it, I believe)
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: af0815 on January 20, 2019, 03:35:09 pm
I thought this was already fixed.....(because I fixed it, I believe)
In actual fpc trunk (40937), the baudrates for cpuarm not changed. I am on fpc fixes32.

But i think higher bausrates did not work out of the box. If i read the RasPi Forums, you have to use resistors (33 Ohm) and to deal with the cables for higher baudrates. So it have to fixed in synapse.

Edit: http://fw.hardijzer.nl/?p=138 looks like the baud rate is/was limited to 187500 baud. But you have to fiddle with the kernelinformation and more. See the link from 2012.
Title: Re: RasPi: How can i detect the actual local IP of the Ethernet Port
Post by: af0815 on January 20, 2019, 04:05:59 pm
The is a patch for the arm issu on the Sourceforge Page https://sourceforge.net/p/synalist/bugs/43/ since April 2018 but not applied.

Code: Pascal  [Select]
  1. --- synaser_r207.pas    2018-04-14 07:16:03.622511742 -0700
  2. +++ synaser.pas 2018-04-14 07:16:38.146908883 -0700
  3. @@ -200,7 +200,11 @@
  4.    {$IFDEF BSD}
  5.    MaxRates = 18;  //MAC
  6.    {$ELSE}
  7. -   MaxRates = 30; //UNIX
  8. +    {$IFDEF CPUARM}
  9. +    MaxRates = 19; //CPUARM
  10. +    {$ELSE}
  11. +    MaxRates = 30; //UNIX
  12. +    {$ENDIF}
  13.    {$ENDIF}
  14.  {$ELSE}
  15.    MaxRates = 19;  //WIN
  16. @@ -229,6 +233,7 @@
  17.  {$IFNDEF BSD}
  18.      ,(460800, B460800)
  19.    {$IFDEF UNIX}
  20. +    {$IFNDEF CPUARM}
  21.      ,(500000, B500000),
  22.      (576000, B576000),
  23.      (921600, B921600),
  24. @@ -240,6 +245,7 @@
  25.      (3000000, B3000000),
  26.      (3500000, B3500000),
  27.      (4000000, B4000000)
  28. +    {$ENDIF}
  29.    {$ENDIF}
  30.  {$ENDIF}
  31.      );
  32.