Today I fired up my code on my Nano 33 IoT and instead of connecting with DHCP to my local network it connected to the WAN. I stripped the code down to the basics below, and it still connects to a WAN. It connected to the LAN address before.
Does anyone know what might be going on?
#include <Arduino_LSM6DS3.h>
#include <WiFiNINA.h>
#include <RTCZero.h>
// WiFi Credentials (edit as required)
char ssid[] = "MyNetwork"; // Wifi SSID
char pass[] = "MyPassword"; // Wifi password
int keyIndex = 0; // Network key Index number (needed only for WEP)
// Object for Real Time Clock
RTCZero rtc;
int status = WL_IDLE_STATUS;
// Time zone constant - This we might want to change to someone elses time zone.
// TODO: How about getting this from the network itself?
const int GMT = -7;
// Initialize the Wifi client
WiFiClient client;
WiFiServer server(443); // define the server and port needed to access.
// Connect to Wifi
void connectToAP() {
// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true);
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network
delay(1000); // wait 1 second for connection
Serial.print("Status: "); Serial.println(status);
}
Serial.println("Connected...");
// print your MAC address:
byte mac[6];
WiFi.macAddress(mac);
printMacAddress(mac);
printWifiStatus();
}
// =================================================================
// The startup of the system
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(115200);
// WARNING - When you get to the point where the board is working on its own
// the following "Serial" wait must be removed or the code will sit here and
// wait for the Serial Monitor and USB cable connection from the IDE.
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
connectToAP();
server.begin(); // Start the web server
}
// =================================================================
// =================================================================
// The ongoing processing on the device.
void loop() {
WiFiClient client = server.available(); // listen for incoming clients
if (client) {
Serial.println();
ParseHttpRequest(client);
// give the web browser time to receive the data
delay(1);
// close the connection:
client.flush();
client.stop();
}
}
// Read the full URL line sent to the server.
String readWifiLine(WiFiClient &client, bool ¤tLineIsBlank){
String output_string = "";
while(client.available()){
char c = client.read();
if(c == '\n'){
Serial.println("NEW LINE FLAGGED");
currentLineIsBlank = true;
return output_string;
}
else if(c != '\r'){
output_string += c;
currentLineIsBlank = false;
}
}
return output_string;
}
// Parse a client posting to the web server.
void ParseHttpRequest(WiFiClient &client){
bool currentLineIsBlank = true; // an http request ends with a blank line
String start_key = "DATA=&"; // key to assign start of post data
String currentLine = "";
while(client.available()){
char c = client.read();
if(c == '\n'){
currentLineIsBlank = true;
// We are done reading the request and can process the values.
if(currentLine.endsWith(" HTTP/1.1")){
currentLine = currentLine.substring(0,currentLine.length()-9);
}
if(currentLine.startsWith("GET /")){
htmlSendReply(currentLine);
}
else if(currentLine.startsWith("POST /")){
Serial.print("Current Line in POST: ");
Serial.println(currentLine);
}
break;
}
else if(c != '\r'){
currentLine += c;
// We are not at the end so we keep going
currentLineIsBlank = false;
}
}
}
// The following would send a web page back to a connection made from a web browser.
void htmlSendReply(String currentLine){
Serial.println("Sending Reply");
client.println("HTTP/1.1 200 OK");
client.println("Content-Type:text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("Controller 1.0");
client.println("Received URL: ");
client.print(currentLine);
client.print("Hello World");
client.println("</html>");
Serial.println("Reply Sent");
}
void printMacAddress(byte mac[]) {
Serial.print("MAC: ");
for (int i = 5; i >= 0; i--) {
if (mac[i] < 16) {
Serial.print("0");
}
Serial.print(mac[i], HEX);
if (i > 0) {
Serial.print(":");
}
}
Serial.println();
}
// Print results to serial monitor
void printWifiStatus() {
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
void print2digits(int number) {
if (number < 10) {
Serial.print("0");
}
Serial.print(number);
}
void printTime()
{
print2digits(rtc.getHours() + GMT);
Serial.print(":");
print2digits(rtc.getMinutes());
Serial.print(":");
print2digits(rtc.getSeconds());
Serial.println();
}
void printDate()
{
Serial.print(rtc.getDay());
Serial.print("/");
Serial.print(rtc.getMonth());
Serial.print("/");
Serial.print(rtc.getYear());
Serial.print(" ");
}
The IP address that it comes back with should be in the 10.0.1.2xx range, but instead it is coming back with 192.168.1.74.
If I go to my router reports WAN IP (connection to the internet) as 192.168.1.102.
If the Arduino were giving the 192.168.1.102 IP I would think that the code in the library was sending the WAN address in the call WiFi.localIP(), but it isn't. The other thing that is odd is that the SSID should be needed for connection to the WAN and I have not provided that to it. This got me to thinking that maybe the "connection" isn't actually happening. To test this I modified the code for "connectToAP" to the following:
// Connect to Wifi
void connectToAP() {
// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true);
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network
delay(1000); // wait 1 second for connection
}
// Checking all the values from the wd_definitions file.
if (status == WL_CONNECT_FAILED){
Serial.println("Status: WL_CONNECT_FAILED");
} else if (status == WL_IDLE_STATUS){
Serial.println("Status: WL_IDLE_STATUS");
} else if (status == WL_NO_SSID_AVAIL){
Serial.println("Status: WL_NO_SSID_AVAIL");
} else if (status == WL_SCAN_COMPLETED){
Serial.println("Status: WL_SCAN_COMPLETED");
} else if (status == WL_SUCCESS){
Serial.println("Status: WL_SUCCESS");
} else if (status == WL_FAILURE){
Serial.println("Status: WL_FAILURE");
} else if (status == WL_NO_SHIELD){
Serial.println("Status: WL_NO_SHIELD or WL_NO_MODULE");
} else if (status == WL_CONNECTED){
Serial.println("Status: WL_CONNECTED");
} else if (status == WL_CONNECTION_LOST){
Serial.println("Status: WL_CONNECTION_LOST");
} else if (status == WL_DISCONNECTED){
Serial.println("Status: WL_DISCONNECTED");
} else if (status == WL_AP_LISTENING){
Serial.println("Status: WL_AP_LISTENING");
} else if (status == WL_AP_CONNECTED){
Serial.println("Status: WL_AP_CONNECTED");
} else if (status == WL_AP_FAILED){
Serial.println("Status: WL_AP_FAILED");
} else {
Serial.print("Status: Unknown with a value of: "); Serial.println(status);
}
Serial.println("Connected...");
// print your MAC address:
byte mac[6];
WiFi.macAddress(mac);
printMacAddress(mac);
printWifiStatus();
}
The output from this change though was WL_CONNECTED.
I figured it out. Firstly, the only thing coming out of the while look could be success otherwise it stays in there. The issue was that I had changed the connection delay time to 1 second which was in the comment from the sample I used. Moving it back to 10000 (10 seconds) and the delay is enough for the connection to be properly completed and reported.
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network
delay(10000); // wait 10 second for connection
}
I need to see if there is some other delay through a While that can be done rather than just 10 seconds. Problem for another day, if a problem at all.
Is never a WAN IP. 10.0.0.0=>10.255.255.255 is Class A private IP for large networks like business seats. 172.16.0.0 => 172.31.255.255. is Class B for medium networks. 192.168.0.0=>192.168.255.255 is for Class C small networks like home use. With subnetmask 255.255.255.255 there are max 256 adresses. With subnetting more.
You might think so, but the WAN router from the ISP is a totally different SSID and locked down for broadcast. I think this is just a default somewhere (even though I did a GitHub search of the code with no success) in the WiFi setup, and because the delay was not long enough the proper value was not changed to the real result.
That is what I was expecting as well and why I cut the delay down (why wait for something that should already be done). Yet when I added the extra time it works.
Doing some extra testing at setting the time back to a value of 1000 (1 second) and power cycling the Arduino I get the 192.168.1.74 address. I then tested with the delay to 2, then 3, and finally 4 seconds before I get the proper IP reporting.
Might not be what you expected, but that is what I am seeing. I suspect the initial connection is made, but the allocation of the assigned IP address has not completed yet.
I suspect the delay was originally put in to manage the cycling of the While loop, but from my testing the While loop is not needed because there is only ever one return when the driver is completed (failure or success). The delay in the samples then just based that the total exchange had not yet completed.
The WAN modem/router does offer DHCP and I was about to say that its only connection is through my Asus mesh that handles the internal DHCP. Then I remembered that last weekend when I was cleaning up the network configuration I ran a second CAT 6 cable between the WAN and the Asus in order to try a bridging configuration, but I didn't get back to it. This means that there appears to have been a means by which the Asus could be bypassed. Unfortunately it likely also has a potential to have offered a bypass of my NAT and other security measure for which I need to see if anything has been compromised.
A very interesting turn for me. thanks for pushing me on this front.
It is interesting that a longer "delay" did appear to push the Arduino to my preferred internal network.
It's not random to the ESP32. It requested an IP address from a DHCP server on the network it connected to and accepted the answer it got from the DHCP server. If you are running multiple DHCP servers on the same network then it's a network topology design issue rather than an ESP IDF issue
Shouldn't it only make the request though of the SSID that is named and not all? Even the password should not work given the responding DHCP has a very different password.
It might be the process that I don't understand but it does seam like it made a request for the IP, got that and then responded as connected, but the authentication to the network still needed to happen.
What do the while loop? It leaves the ESP in a loop until it becomes a IP from your router.
delay(1000); makes that the loop wait for 1 second for the connection was check again. Maybe it takes 10 seconds to become a clear connection. 192.168.1.4 is the standard IP programmed in the librarie. Set your device in AP mode and it uses these IP.
What can you see every loop with Serial.println(ssid);?
What is then the reason that it didn't connect to the correct SSID and gives a wrong IP? I have 2 2,4MHz DHCP servers with each another SSID, I never have connected to the wrong network.