Skip to content

Connect to AP using SSID, Password, and BSSID? How exactly? #9163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
madmacks59 opened this issue Jul 12, 2024 · 17 comments
Closed

Connect to AP using SSID, Password, and BSSID? How exactly? #9163

madmacks59 opened this issue Jul 12, 2024 · 17 comments

Comments

@madmacks59
Copy link

Platform

  • Hardware: ESP-12
  • Development Env: Arduino IDE 2.x
  • Operating System: Windows
  • Module: Generic ESP8266 Module

Problem Description

I've been trying to connect to a specific AP using its SSID/Password and the MAC address of the AP. I have several APs spread around my property and most of my devices attach to the strongest AP. In my particular application I want the ESP8266 to connect to a specific AP and ignore all the others. To do this I should be able to use the "WiFi.begin(ssid, password, channel, bssid, connect)" option.

But, I've tried multiple ways to define the bssid parameter properly and none of the are working. Can someone provide an example of how exactly to do this within the Arduino IDE?

And example of the definition code and the call code would really help...

@JAndrassy
Copy link
Contributor

@madmacks59
Copy link
Author

madmacks59 commented Jul 12, 2024

Yes, I know, I’ve read that…what I’m looking for is an example of the implementation in code. For example, do i use the call like…

WiFi.begin(“myssid”, “mypassword”, 7, “01:02:C1:33:F1”)
Or do I define variables and pass them (which I’ve tried and get compile errors)?

When I try using variables I get a type error for the bssid as the variable type doesn’t match what the method wants, and I cant figure out how to implement the MAC address as the required variable type.

@JAndrassy
Copy link
Contributor

so there is no issue. ok.

@madmacks59
Copy link
Author

? What ?

@madmacks59
Copy link
Author

madmacks59 commented Jul 12, 2024

Running a WiFI scan sketch on the ESP8266 shows the following...

13:24:46.572 -> Starting WiFi scan...
13:24:48.779 -> 4 networks found:
13:24:48.779 -> 00: [CH 03] [3C:52:A1:D4:7F:B5] -68dBm * V 802.11b/g/n WPS WIFI-24
13:24:48.779 -> 01: [CH 07] [E8:9C:25:71:85:70] -31dBm * V 802.11b/g/n WPS WIFI-24
13:24:48.779 -> 02: [CH 07] [42:F5:20:05:FB:DB] -68dBm V 802.11b/g ESP-05FBDB
13:24:48.779 -> 03: [CH 10] [3C:84:6A:16:D8:0E] -81dBm * V 802.11b/g/n WPS WIFI-24

FYI the ESP shown above is a different device that is connected to the "01" AP, it is
not the ESP in the set up I'm working on now...

=============================================================================

In the code I've imlemented the following...

// Variable definitions

const char *ssid = "WIFI-24";
const char *password = "sillyPassword;
const byte bssid[] = {0xE8, 0x9C, 0x25, 0x71, 0x85, 0x70};

// Down in the conncect code

bool wifiConnect() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password, 07, bssid);
if (WiFi.status() == WL_CONNECTED) {
delay(1000);
Serial.println("Connected to Wi-Fi network");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
return true;
} else {
Serial.println("Wi-Fi connection failed!");
Serial.println(WiFi.status());
return false;
}
}

When I run the code I get...
07:45:57.655 -> Wi-Fi connection failed!
07:45:57.655 -> 7

If I change the WiFi.begin code to "WiFi.begin(ssid, password);" and
rename the SSID to a unique name like "WIFI-24-X" on the "01" AP and
in the code things run just fine.

So it seems to me that the issue is that the ESP is seeing three APs
advertising "WIFI-24" and fails to pick the strongest signal AP.

The methond WiFi.begin() implements things as follows as far as I
can tell...

Parameters:

const char * ssid
const char * passphrase = 0
int32_t channel = 0 (optional)
const uint8_t * bssid = 0 (optional)
bool connect = true (optional)

So I believe my basic issue is I really don't understand how to implement
the bssid as a "const uint8_t" variable, which means my definition in the above
example is crap. So, that's why I'm asking for a code snippet that shows how to
define the variable properly to pass to the begin() method and possibly how to
use the method without needing to specifiy the channel at all as it could change
on router/AP reboot...

@JAndrassy
Copy link
Contributor

add WiFi.waitForConnectionResult() after WiFi.begin

@madmacks59
Copy link
Author

Ok...I'll give that a try. Thank you.

But...

Isn't there anyone that can actually answer the question I'm asking? What I want to learn/understand is how to implement the method as it's defined and published. The library says you should be able to pass the MAC address of the AP you want to connect with, right? But nowhere in the example code or the document is there an actual explanation of how to actually do it. Google searches, and I've done a lot of searching, doesn't turn up a single example of how these parameters can be used.

@JAndrassy
Copy link
Contributor

you don't wait until it connected so you can't know if it connects to bssid or strongest or anything

@madmacks59
Copy link
Author

The function is actually "WiFi.waitForConnectResult()" I think...at least that's what auto complete shows...not that it makes much of a diff. But the real question is the previous one, how to implement the WiFi.begin() properly using it's defined parms...

@JAndrassy
Copy link
Contributor

you have begin right

@madmacks59
Copy link
Author

Code is shown above. Yes... there is a WiFi.begin(). And after adding the waitFor the wait just times out (-1 returned using 2000 as the timeout). Second loop thru it does connect (using the unique ssid), so I'll play around with the timing and see if it's the radio taking a few seconds to fire up. But, still looing for the info on how to implement the bssid parm...

@madmacks59
Copy link
Author

madmacks59 commented Jul 12, 2024

So... There was apparently some issue with timing.... I reset the router/ap to use the redundant wifi ssid, updated my code with a few delay(500) statements, added back in the bssid definition and the full bssid begin, unplugged, waited for a minute, and plugged back in, and was surprised that things apparently work now. Anyway, below is the code that seems to be working now...

`
/*********
Gary M - Propane controller
This reads three tempurature sensors and reports them via MQTT and WiFi to the MFR MQTT
server. It also looks at the temp reported on sensor #1 (address 0) and if the reported
temp is at or below 5 degrees celsius (41 degrees fahrenheit) it opens the main propane
valve on the shed heater. It keeps the valve open until the temp reaches 10 degrees
celsius (50 degrees fahrenheit). At that temp the valve is closed shuting off the heater.
*********/

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// Temp sensor wires connected to D4 (GPIO2)
#define ONE_WIRE_BUS 2
// Set up oneWire to communicate with devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass oneWire reference to Dallas Temp object
DallasTemperature sensors(&oneWire);
// Number of temperature devices found
int numberOfDevices;
// Relay connected to D2 (GPIO4)
const int RELAY_PIN = 4;
// Temp values (in celsius) used to control relay
float onTemp = 5.0;
float hysteresis = 5.0;
// Instantiate device address
DeviceAddress tempDeviceAddress;
// WiFi connection info (SSID, Password)
const char *ssid = "WiFi-24";
const char *password = "dummyPassword";
const byte bssid[] = {0xE8, 0x9C, 0x25, 0x71, 0x85, 0x70};
// MQTT broker information
const char *mqtt_broker = "192.168.1.98";
const char *topic = "house/waterPump";
const int mqtt_port = 1883;
const char *client_id = "ESP8266-HousePump";
// Array of float temp values for the sensors
float sensorTemp[3] = {0,0,0};
// Used to generate the MQTT message packet which looks like...
// {"Topic":"house/pumpShed","Gas":"Off","Temp1":99.9,"Temp2":99.99,"Temp3":99.99}
char msgTopic[26] = "{"Topic":"house/pumpShed"";
char msgGas[13] = ","Gas":"Off""; // Default is Gas Off aka relay off
char msgGasOff[13] = ","Gas":"Off"";
char msgGasOn[12] = ","Gas":"On"";
char msgSen1[10] = ","Temp1":";
char msgSen2[10] = ","Temp2":";
char msgSen3[10] = ","Temp3":";
char msgSen4[2] = "}";
char mqttTmp1[6];
char mqttTmp2[6];
char mqttTmp3[6];
char mqttMsg[80];
// Instantiate the WiFi object
WiFiClient espClient;
// Instantiate the MQTT object
PubSubClient mqttClient(espClient);

void setup() {
// Start serial port
Serial.begin(9600);
Serial.println("********** Just Rebooted **********");
// Initialie the relay pin
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
// Start up the sensor library
sensors.begin();
// Waid a sec for sensors to start
delay(1000);
// Grab a count of devices on the oneWire bus
numberOfDevices = sensors.getDeviceCount();
Serial.print("Locating sensor devices...Found ");
Serial.print(numberOfDevices, DEC);
Serial.println(" devices.");
if (numberOfDevices==0) {
Serial.println("Found no temperature sensors, rebooting...");
ESP.restart();
}
// Loop through each device & print out address
for (int i = 0; i < numberOfDevices; i++) {
if (sensors.getAddress(tempDeviceAddress, i)) {
Serial.print("Found device ");
Serial.print(i, DEC);
Serial.print(" with address: ");
printAddress(tempDeviceAddress);
Serial.println();
} else {
Serial.print("Found ghost device at ");
Serial.print(i, DEC);
Serial.println(" but could not detect address. Check power and cabling");
}
}
mqttClient.setServer(mqtt_broker, mqtt_port);
// Wait a second for the radio to fully start...
delay(1000);
if (wifiConnect()) {
if (mqttConnect()) {
Serial.println("Initial connection to WiFi & MQTT Broker was successful...");
mqttClient.disconnect();
}
} else {
Serial.println("Initial connection to WiFi Failed...");
}
}

void loop() {
// Read and process the temp sensors
sensors.requestTemperatures();
// Wait for sensor buss to reply
delay(500);
Serial.println("--------------------------------------------------");
// Loop through each device and print out temp data
for (int i = 0; i < numberOfDevices; i++) {
// Get oneWire address
if (sensors.getAddress(tempDeviceAddress, i)) {
// Output the device ID
Serial.print("Device: ");
Serial.print(i, DEC);
Serial.print("\t");
// Get the Temp data for the sensor
float tempC = sensors.getTempC(tempDeviceAddress);
sensorTemp[i] = tempC;
Serial.print("Temp C: ");
Serial.print(tempC);
Serial.print("\tTemp F: ");
// Convert tempC to Fahrenheit and print
Serial.println(DallasTemperature::toFahrenheit(tempC));
if (i == 0 ) { // If First Sensor (aka 0)
if (tempC <= onTemp) { // If tempurature is equal to or lower than on temp
if (!digitalRead(RELAY_PIN)) { // If relay is off turn it on
digitalWrite(RELAY_PIN, HIGH);
Serial.println("Relay On");
strcpy(msgGas, msgGasOn);
}
} else { // else
if (tempC >= (onTemp + hysteresis)) { // if tempurature is equal to or greater than off temp
if (digitalRead(RELAY_PIN)) { // If relay is on turn it off
digitalWrite(RELAY_PIN, LOW);
Serial.println("Relay Off");
strcpy(msgGas, msgGasOff);
}
}
}
}
}
}
// If WiFi is disconnected try to reconnect
if (WiFi.status() != WL_CONNECTED) { wifiConnect(); }

// Build the MQTT message if WiFi and MQTT Connected
if (WiFi.status() == WL_CONNECTED) {
if (mqttConnect()) {
// Put together the message payload
strcpy(mqttMsg, msgTopic);
strcat(mqttMsg, msgGas);
strcat(mqttMsg, msgSen1);
dtostrf(sensorTemp[0], 5, 2, mqttTmp1);
strcat(mqttMsg, mqttTmp1);
strcat(mqttMsg, msgSen2);
dtostrf(sensorTemp[1], 5, 2, mqttTmp2);
strcat(mqttMsg, mqttTmp2);
strcat(mqttMsg, msgSen3);
dtostrf(sensorTemp[2], 5, 2, mqttTmp3);
strcat(mqttMsg, mqttTmp3);
strcat(mqttMsg, msgSen4);
// Send the message
if (mqttClient.publish(topic, mqttMsg, false)) {
Serial.println("MQTT Msg Published...");
} else {
Serial.println("MQTT Msg Failed...");
Serial.print(mqttClient.state());
}
// Disconnect from MQTT Broker
mqttClient.disconnect();
}
}
Serial.println(""); // Force print buffer out just in case
// delay(3001000); // Wait 5 minute
delay(30
1000); // Wait 30 seconds
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress) {
for (uint8_t i = 0; i < 8; i++) {
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
}
}

// Get a WiFi connection but don't freak if it fails
bool wifiConnect() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid,password,07,bssid);
int chkstat = WiFi.waitForConnectResult(5000);
Serial.print("Wait for Connection chkstat=");
Serial.println(chkstat);
Serial.printf("BSSID: %s\n", WiFi.BSSIDstr().c_str());
if (WiFi.status() == WL_CONNECTED) {
delay(500);
Serial.println("Connected to Wi-Fi network");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.print("SSI Strength: ");
Serial.println(WiFi.RSSI());
return true;
} else {
Serial.println("Wi-Fi connection failed!");
Serial.println(WiFi.status());
return false;
}
}

// Only call if there is a WIFI connection!
// Connected to MQTT but don't freak if it fails.
bool mqttConnect() {
if (mqttClient.connect(client_id)) {
Serial.println("MQTT broker connected");
return true;
} else {
Serial.print("MQTT Broker connection failed!");
Serial.print(mqttClient.state());
return false;
}
}

`

@JAndrassy
Copy link
Contributor

JAndrassy commented Jul 13, 2024

I guess automatic connection to remembered AP was happening parallel with setup(). use some of WiFi.setPeristent(false), WiFi.setAutoReconnect(false), WiFi.erase()

@madmacks59
Copy link
Author

It appears that the issue was possibly due to timing. I'd suggest that some additional examples be added to the doco that show how to use WiFi.begin(ssid,password,channel,bssid) with various options and how to define the parameters more clearly. But that's just the opinion of a relative newbie...

@madmacks59
Copy link
Author

Dang it! I added a bit of unrelated code and now the connection is failing again, exactly as before. I'm reopening this issue again, as I guess the connect with BSSID still is funky...

@madmacks59 madmacks59 reopened this Jul 13, 2024
@madmacks59
Copy link
Author

OK, I found some other info and this may be the issue... I'm running an ASUS RT-AX86U Pro Router and that router uses "802.11ax / WiFi 6 mode" mode as its default. The info I found suggests that WiFi 6 Mode is an issue with the ESP8266 radio, so I turned off the WiFi 6 Mode and now things seem to work reliably. So, is there an issue on the ESP8266 with WiFi 6?

@madmacks59
Copy link
Author

Apparently there is a separate ticket open around this issue. The issues has to do with the newer board cores and the solution is to revert to core 2.5.2 and recompile without some of the newer functions (like WiFi scan). I did that and the board has been processing just fine for the last two days. And with the older core I didnt need to specific the AP MAC address as the library connects to the strongest AP just fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants