1

I can get the client mac-address in Access Point mode (AP_MODE), see suGetClientMacAddress() function below.Found this code on the internet. I try to figure out the MAC-address of clients in WiFi.mode(STA_MODE);, however cannot find any useful info on this, impossible? And when it seems it is impossible, why is it impossible? Or is there still a 'trick' to get it working?

Below you can find the working function/version in AP_MODE

The library I am using the default ESP (v. 2.4.0) library and the Async web/sockets library: https://github.com/me-no-dev/ESPAsyncWebServer


#define SU_WCFG_SERVER_ASYNC


 ........
 ........

 #ifdef SU_WCFG_SERVER_ASYNC
  #define SUWebSocketServer       AsyncWebSocket
  #define SUWebServerRequest      AsyncWebServerRequest
 #else
  ......
 #endif

 extern "C" {
    #include "user_interface.h"   // Required for some low level wifi functions
 }

............
............


String suIpAddressToString( IPAddress ipAddress )
{ 
  return String( ipAddress[0] )+"."+
         String( ipAddress[1] )+"."+
         String( ipAddress[2] )+"."+
         String( ipAddress[3] );
}

IPAddress suStringToIpAddress( String ipAddress )
{ 
  IPAddress ip = IPAddress( 0, 0, 0, 0 );
  char* pStr   = (char*)ipAddress.c_str();
  uint8_t i    = strlen( pStr );
  uint8_t iPos = 4;

   // Test before start 
  if( i > 6 && pStr[i-1] != '.' )
  {
    while( i-- && iPos )    
    {
      if( pStr[i] == '.' || i == 0 )
      {
        ip[--iPos] = String( (char*)&pStr[i+(i>0)] ).toInt();
        pStr[i] = 0; // set null termination to truncate
      }
    }
  }

  return ip;
}

String suGetClientIp( SUWebServerRequest* request )
{ 
  if( request )
   { return suIpAddressToString( IPAddress( request->client()->remoteIP() )); }

  return "";  
}

The function:

String suGetClientMacAddress( SUWebServerRequest* request )
{ 
  if( request )
   {  
     struct ip_addr*       IPaddress;
     IPAddress             ip;
     struct station_info*  stat_info = wifi_softap_get_station_info();
     String                sClientIp = suGetClientIp( request );

     Serial.print( "Client ip: " );
     Serial.println( sClientIp );

     if( sClientIp.length() > 0 )
     {
      while( stat_info ) 
      {
        IPaddress = &stat_info->ip;
        ip = IPaddress->addr;

        if( suIpAddressToString( ip ) == sClientIp )
        {
           // Kind of rude and ugly to exit a loop and function this way
           // however it works with less 'check' overhead. OK to me.
          return String( stat_info->bssid[0], HEX )+":"+
                 String( stat_info->bssid[1], HEX )+":"+
                 String( stat_info->bssid[2], HEX )+":"+
                 String( stat_info->bssid[3], HEX )+":"+
                 String( stat_info->bssid[4], HEX )+":"+
                 String( stat_info->bssid[5], HEX );
        } 

        stat_info = STAILQ_NEXT(stat_info, next);
      }
     } 
   }

  return "";  
}

Any hints to get it working in STA_MODE?

Codebeat
  • 6,501
  • 6
  • 57
  • 99

2 Answers2

0

Hint:

- stations (clients) connect to an AP (Access Point - server)
- an AP generally hosts RF (radio) mechanisms for the connections of stations

An ESP8266 can be either a station or AP, neither or both.

WiFi stations (as clients) do not usually communicate directly with each other unless special provisions are made to do so, such as in mesh / Ad Hoc networks or with a physical (cable ;) connection.

ekim
  • 1
0

I found an example made using ESP8266. I also made one myself for ESP32 here.

To briefly summarise the 2 examples, below is a code snippet that can retrieve the corresponding MAC address an IP in STA_MODE:

#include <lwip/etharp.h>
...
eth_addr *get_sta_mac(const uint32_t &ip)
{
    ip4_addr requestIP{ip};
    eth_addr *ret_eth_addr = nullptr;
    ip4_addr const *ret_ip_addr = nullptr;
    etharp_request(netif_default, &requestIP);
    etharp_find_addr(netif_default, &requestIP, &ret_eth_addr, &ret_ip_addr);
    return ret_eth_addr;
}
...

The above code is tested with arduino-esp32.