Get BSSID with ESP8266

I'm trying to get my ESP8266's connected-to AP MAC address. On another thread someone suggested trying the WiFi.BSSID() example but it won't compile for me.

error: invalid conversion from 'uint8_t* {aka unsigned char*}' to 'char*' [-fpermissive]

If I try

byte *bssid = WiFi.BSSID();

instead it says Error compiling for board Generic ESP8266 Module

Anyone know how to get the ESP8266's connected AP's MAC?

That example does not compile. You need to change

  if ( status != WL_CONNECTED) {

to

  if ( WiFi.status() != WL_CONNECTED) {

And then it compiled just fine for me. esp8266 boards v 2.74 -> Generic ESP8266 Module

m_elias:
error: invalid conversion from 'uint8_t* {aka unsigned char*}' to 'char*' [-fpermissive]

Post the code that caused that error message. And, post the complete error message.

//#include <WiFi.h>
#include "ESP8266WiFi.h"

//SSID of your network
char ssid[] = "ssid";
//password of your WPA Network
char pass[] = "ssidPW";

void setup(){
  Serial.begin(115200);
  Serial.print("Connecting...\r\n");
  WiFi.begin(ssid, pass);
  Serial.print("Connected\r\n");

  if ( WiFi.status() != WL_CONNECTED) {
    Serial.println("Couldn't get a wifi connection");
    while(true);
  } else {
    byte bssid[6];
    WiFi.BSSID(bssid);    
    Serial.print("BSSID: ");
    Serial.print(bssid[5],HEX);
    Serial.print(":");
    Serial.print(bssid[4],HEX);
    Serial.print(":");
    Serial.print(bssid[3],HEX);
    Serial.print(":");
    Serial.print(bssid[2],HEX);
    Serial.print(":");
    Serial.print(bssid[1],HEX);
    Serial.print(":");
    Serial.println(bssid[0],HEX);
  }
}

void loop(){
  yield();

Using Wifi.h results in a wdt reset.

Connecting...

 ets Jan  8 2013,rst cause:4, boot mode:(3,0)

wdt reset
load 0x4010f000, len 3456, room 16 
tail 0
chksum 0x84
csum 0x84
va5432625
~ld

Using ESP8266WiFi.h results in the error on line 23 WiFi.BSSID(bssid);

invalid conversion from 'byte* {aka unsigned char*}' to 'uint8_t {aka unsigned char}' [-fpermissive]

gfvalvo:
And, post the complete error message.

m_elias:
Using ESP8266WiFi.h results in the error on line 23 WiFi.BSSID(bssid);

invalid conversion from 'byte* {aka unsigned char*}' to 'uint8_t {aka unsigned char}' [-fpermissive]

That's not the complete error message. There's a lot more information avaqilable in that black window at the bottom of the Arduino IDE post it ALL.

C:\Users\Matt\AppData\Local\Temp\arduino_modified_sketch_282347\sketch_feb24a.ino: In function 'void setup()':
sketch_feb24a:23:21: error: invalid conversion from 'byte* {aka unsigned char*}' to 'uint8_t {aka unsigned char}' [-fpermissive]
     WiFi.BSSID(bssid);
                     ^
In file included from C:\Users\Matt\Seafile\Programming\Arduino\arduino-1.8.13\portable\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/ESP8266WiFi.h:36:0,
                 from C:\Users\Matt\AppData\Local\Temp\arduino_modified_sketch_282347\sketch_feb24a.ino:2:
C:\Users\Matt\Seafile\Programming\Arduino\arduino-1.8.13\portable\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/ESP8266WiFiScan.h:49:19: error:   initializing argument 1 of 'uint8_t* ESP8266WiFiScanClass::BSSID(uint8_t)' [-fpermissive]
         uint8_t * BSSID(uint8_t networkItem);
                   ^
Using library ESP8266WiFi at version 1.0 in folder: C:\Users\Matt\Seafile\Programming\Arduino\arduino-1.8.13\portable\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi 
exit status 1
invalid conversion from 'byte* {aka unsigned char*}' to 'uint8_t {aka unsigned char}' [-fpermissive]

It won't let me post all the text, so here's the error part.

Think I see the problem. There are two overloads of the 'BSSID()' function available to the WiFi object because of inheritance by the ESP8266WiFiClass class.

From the ESP8266WiFiSTAClass class, there's this prototype:

uint8_t * BSSID();

From the ESP8266WiFiScanClass class, there's this prototype:

uint8_t * BSSID(uint8_t networkItem);

The call you're trying to make matches neither of those prototypes. Pick one and use it correctly. I'd start by trying the ESP8266WiFiSTAClass version.

Also, you code to handle failure to connect with the WiFi is bad. You're bailing out on the first try if it's not connected yet. Then, you go into a 'while' loop with no yield function to prevent WDT resets.

Thanks for the direction.

That code is just from the WiFi.BSSID() example, trying to get it working before applying to my project.

Is there any reason you are using Wifi.h?

I use ESP8266WiFi.h , and the MAC address is simply WiFi.macaddress()

Here is how I connect my ESP to the WiFi.
This is a separate tab in my sketches and I just call setup_wifi() from my setup() function.

//setup_wifi
//================= Connect the ESP to the router =================
//Connect to WiFi network so we can reach the MQTT broker and publish messages to topics.

/*
  Make sure you include at the start of the sketch:
  //---------- wifi ----------
  #define HOSTPREFIX "CGM-"   //18 chars max (Used for MQTT)
  #include "ESP8266WiFi.h"    //Not needed if also using the Arduino OTA Library...
  #include "D:\River Documents\Arduino\libraries\Kaywinnet.h"  \\ WiFi credentials
  char macBuffer[24];         //Holds the last three digits of the MAC, in hex.
  char hostNamePrefix[] = HOSTPREFIX;
  char hostName[24];          //Holds hostNamePrefix + the last three bytes of the MAC address.
*/

void setup_wifi() {
#ifndef Kaywinnet
#include <kaywinnet.h>
#endif
  byte mac[6];                     ////the MAC address of your Wifi

  Serial.println(F("\n"));
  Serial.print(F("Connecting to "));
  Serial.println(MY_SSID);


  WiFi.mode(WIFI_STA);
  WiFi.enableInsecureWEP();
  WiFi.begin(MY_SSID, MY_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(WiFi.status()); Serial.print(F(" "));
  }
  Serial.println(F("\nWiFi connected, "));
  Serial.print(F("MAC Address: "));
  Serial.println(WiFi.macAddress());
  Serial.print(F("IP address: "));
  Serial.println(WiFi.localIP());


  //Get the last three numbers of the mac address.
  //"4C:11:AE:0D:83:86" becomes "0D8386" in macBuffer.
  WiFi.macAddress(mac);
  snprintf(macBuffer, sizeof(macBuffer), "%02X%02X%02X", mac[3], mac[4], mac[5]);

  //Build hostName from hostNamePrefix + last three bytes of the MAC address.
  strcpy(hostName, hostNamePrefix);
  strcat(hostName, "-");
  strcat(hostName, macBuffer);

  Serial.print(F("hostName = \""));
  Serial.print(hostName);
  Serial.println(F("\""));

}

SteveMann:
Is there any reason you are using Wifi.h?

I use ESP8266WiFi.h , and the MAC address is simply WiFi.macaddress()

Wifi.h is what the BSSID reference page used for an example but I am using ESP8266WiFi.h in my project sketch. For now, I'm trying to get the example sketch to work first, it seems it's not intended for the ESP8266. Unfortunately WiFi.macaddress() shows your ESP's (local) MAC, I'm looking for the MAC of the AP that it's connected to (also known as BSSID). That being said, I still used parts of your code to get the BSSID example working with WiFi.macAddress and WiFi.localIP (thank you), then I continued down the path @gfvalvo directed me and ended up with the following.

#include "ESP8266WiFi.h"

char ssid[] = "ssid";
char pass[] = "password";

void setup(){
  Serial.begin(115200);
  while(!Serial);
  delay(1000);
  Serial.print("\r\n\nConnecting...");
  WiFi.mode(WIFI_STA);
  WiFi.enableInsecureWEP();
  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(WiFi.status()); Serial.print(F(" "));
  }

  Serial.println(F("\r\n\nWiFi connected to"));
  Serial.print("SSID: ");
  Serial.println(ssid);
  uint8_t *bssid = WiFi.BSSID();
  Serial.print("BSSID: ");
  for (byte i = 0; i < 6; i++){
    Serial.print(*bssid++, HEX);
    if (i < 5) Serial.print(":");
  }

  Serial.println("\r\n\nDevice info");
  Serial.print(F("MAC Address: "));
  Serial.println(WiFi.macAddress());
  Serial.print(F("IP address: "));
  Serial.println(WiFi.localIP());
}

void loop(){
  delay(100);
}

1 Like

It's a little surprising to me that the BSSID() function returns a 'uint8_t *' rather than a 'const uint8_t *' given that it's a pointer an internal member state variable. So that you don't accidently screw it up, better to use:

const uint8_t *bssid = WiFi.BSSID();

Thanks again, it's working!

My next step is to parse a bssid mqtt payload (using pubsubclient) into a format accepted by

WiFi.begin(ssid, password, 0, targetBSSID);

Something like

uint8_t targetBSSID[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};

My mqtt callback function is

void callback(char* _topic, byte* _payload, unsigned int _length)

Is there a str function to do this? I've spent a fair bit of time reading but I get lost in the data types/pointers. This is what I have so far.

  if (strstr(_topic, "cmd/bssid")){
    if (_length == 17){
      //Serial << "\r\nBSSID\r\n";
      char bssidStr[7] = { 0 };
      byte bssidCnt = 0;
      byte dec = 0;
      byte cnt = 0;
      for (byte i = 0; i < 17; i++){
        if (cnt == 1) dec *= 16;
        //Serial << i << ":" << _payload[i] << " " << dec << " " << cnt << "\r\n";
        if (_payload[i] >= '0' && _payload[i] <= '9'){
          dec += _payload[i] - '0';
          cnt++;
        } else if (_payload[i] >= 'A' && _payload[i] <= 'F'){
          dec += _payload[i] - 55;
          cnt++;
        } // else { // if (_payload[i] == ':'){
        //Serial << i << ":" << _payload[i] << " " << dec << " " << cnt << "\r\n";

        if (cnt >= 2){
          Serial.print("\r\n  ");
          Serial.print(i);
          Serial.print(":");
          Serial.print(dec, HEX);
          //Serial.print(":");
          //bssidStr[bssidCnt] = printf("%02X", dec);
          sprintf(&bssidStr[bssidCnt], "%02X", dec);
          bssidCnt++;
          cnt = 0;
          dec = 0;
          i++;
          //targetBSSID = 
        }
      }
      bssidStr[6] = 0;
      Serial << "\r\nBSSID: " << bssidStr;
    }
    //sprintf(bssidStr, "%02X%02X%02X%02X%02X%02X", _payload[1], _payload[4], _payload[7],_payload[10], _payload[13], _payload[16]);
    //bssidStr[6] = 0;
    //Serial << "\r\ncmd/bssid >" << bssidStr;
    
 /*   if (_length == 17){
      char* ptr; //start and end pointer for strtol
      targetBSSID[0] = strtol(_payload, &ptr, HEX);
      
      for (byte i = 1; i < 6; i++){
        //targetBSSID[i] = strtol(ptr+1, &ptr, HEX);
      }
    }

    return;
  }

My serial output

0000:00:00:04.478 Mqtt in [test/esp01/cmd/bssid] >AA:BB:CC:DD:EE:FF<
  1:AA
  4:BB
  7:CC
  10:DD
  13:EE
  16:FF
BSSID: ABCDEF

So I'm getting the segments assembled but the sprintf output isn't what I expected. It doesn't seem to be outputting HEX.

What is the EXACT format of the ASCII mqtt payload received for setting BSSID? Is each byte of BSSID always represented by 2 characters even if the value is 'F' or lower?

I want to copy paste from a router's GUI or type it in manually so it can be all caps with leading zeros if necessary. Handling upper or lower case would be nice. The separator might not always be a colon but I can ensure there is a separator.

The strtok() function will probably be helpful. It allows specification of multiple delimiter characters.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.