Recent

Author Topic: RasPi: How can i detect the actual local IP of the Ethernet Port  (Read 2937 times)

af0815

  • Sr. Member
  • ****
  • Posts: 360
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.



regards
Andreas

sash

  • Sr. Member
  • ****
  • Posts: 275
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #1 on: January 18, 2019, 11:39:28 pm »
What exactly doesn't work?

Also, what do you mean by "local IP", loopback interface address?
Lazarus 2.0.6 FPC 3.0.4 x86_64-linux-gtk2 -- Ubuntu 19.10 XFCE

af0815

  • Sr. Member
  • ****
  • Posts: 360
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #2 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).

regards
Andreas

HeavyUser

  • Sr. Member
  • ****
  • Posts: 262
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #3 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.  

af0815

  • Sr. Member
  • ****
  • Posts: 360
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #4 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.




 
regards
Andreas

HeavyUser

  • Sr. Member
  • ****
  • Posts: 262
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #5 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.

Thaddy

  • Hero Member
  • *****
  • Posts: 9169
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #6 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/
also related to equus asinus.

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #7 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:
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.

af0815

  • Sr. Member
  • ****
  • Posts: 360
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #8 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
regards
Andreas

af0815

  • Sr. Member
  • ****
  • Posts: 360
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #9 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


regards
Andreas

af0815

  • Sr. Member
  • ****
  • Posts: 360
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #10 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
« Last Edit: January 19, 2019, 05:13:57 pm by af0815 »
regards
Andreas

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #11 on: January 19, 2019, 05:24:10 pm »
A cleaner solution should not involve a connection. There is another thread that uses getifaddrs

avra

  • Hero Member
  • *****
  • Posts: 1714
    • Additional info
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #12 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.
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

af0815

  • Sr. Member
  • ****
  • Posts: 360
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #13 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.
regards
Andreas

avra

  • Hero Member
  • *****
  • Posts: 1714
    • Additional info
Re: RasPi: How can i detect the actual local IP of the Ethernet Port
« Reply #14 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.
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib