0

I am using an ESP8266WiFiHW-628 V0.0.1 to create an access point (code below). While I am able to connect to the AP using a windows machine when I am trying to connect using iOS devices I get "Unable To Join the network ..."

I am using:

  • ESP8266WiFiHW-628 V0.0.1
  • VSCode
  • PlatformIO
  • 5v, 3A power supply (it currently shown max current of 0.8A)
  • iPhone Xs with iOS 18.6.2 and iPhone SE with iOS 18.6.2

Looking for an working example showing how to set up the ESP8266 so iOS devices can connect to it.

I tried :

  • Power supply problems - 4A power supply, showing less than 1A actual demand
  • channels problem - tried 1,6,11. tried to turn off all the other wifi APs
  • Weak signal strength - the iOS is 10cm from the ESP8266
  • Strong pass - tried (when pass is incorrect message is different)
  • IP conflicts - tried 10.0.0.1, 118.118.4.1 ....
  • No DNS - Started a DNS + Setting DNS manually on the iPhone
  • iPhone Private WiFi Address - Turn OFF "Private WiFi Address

Current Code:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <DNSServer.h>

// Create an instance of the AsyncWebServer on port 80.
AsyncWebServer server(80);
DNSServer dnsServer;

// IP configuration for iOS compatibility
IPAddress LocalIP(192, 168, 4, 1);
IPAddress Gateway(192, 168, 4, 1);
IPAddress Subnet(255, 255, 255, 0);

void setup() {
  // Start serial communication for debugging purposes.
  Serial.begin(115200);

  Serial.println("\n--- Starting Setup ---");

  // Create the Access Point with iOS-compatible settings.
  // Configure IP settings first
  WiFi.softAPdisconnect(true);
  
  if (WiFi.softAPConfig(LocalIP, Gateway, Subnet)) {
    Serial.println("AP configuration successful");
    // Create AP with stronger password, channel 6, not hidden, max 4 clients
    if (WiFi.softAP("CircularClockAP", "Clock123!@#", 6, false, 4)) {
      Serial.println("Access Point created successfully");
      // Prevent WiFi sleep for better stability with iOS devices
      WiFi.setSleepMode(WIFI_NONE_SLEEP);
      // Print the IP address of the Access Point.
      Serial.print("AP IP Address: ");
      Serial.println(WiFi.softAPIP());
      Serial.printf("Connected stations: %d\n", WiFi.softAPgetStationNum());
    } else {
      Serial.println("Failed to create Access Point");
    }
  } else {
    Serial.println("Failed to configure AP IP settings");
  }

  // Start DNS server for captive portal
  dnsServer.start(53, "*", LocalIP);
  Serial.println("DNS server started");

  // Add captive portal detection handlers for iOS
  server.on("/hotspot-detect.html", HTTP_GET, [](AsyncWebServerRequest *request){
    Serial.println("iOS captive portal detection");
    request->send(200, "text/html", "<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>");
  });
  
  server.on("/library/test/success.html", HTTP_GET, [](AsyncWebServerRequest *request){
    Serial.println("iOS success page detection");
    request->send(200, "text/html", "<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>");
  });
  
  server.on("/generate_204", HTTP_GET, [](AsyncWebServerRequest *request){
    Serial.println("Android captive portal detection");
    request->send(204); // No Content response for Android
  });
  
  // Handle Apple's connectivity check
  server.on("/connecttest.txt", HTTP_GET, [](AsyncWebServerRequest *request){
    Serial.println("Windows connectivity check");
    request->send(200, "text/plain", "Microsoft Connect Test");
  });

  // Add a simple handler for the root URL.
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    String userAgent = request->getHeader("User-Agent") ? request->getHeader("User-Agent")->value() : "";
    
    // If it's Apple's connectivity check, return success
    if (userAgent.indexOf("CaptiveNetworkSupport") >= 0) {
      Serial.println("Apple connectivity check - returning success");
      request->send(200, "text/html", "<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>");
      return;
    }
    
    // For regular browsers, show configuration page
    Serial.println("HTTP GET request received for the root URL (/).");
    String html = "<!DOCTYPE html><html><head>";
    html += "<meta charset='UTF-8'>";
    html += "<meta name='viewport' content='width=device-width, initial-scale=1.0'>";
    html += "<title>Circular Clock Setup</title>";
    html += "<style>body{font-family:Arial,sans-serif;margin:40px;background:#f5f5f5;}";
    html += ".container{background:white;padding:30px;border-radius:8px;box-shadow:0 2px 10px rgba(0,0,0,0.1);}";
    html += "h1{color:#333;text-align:center;}";
    html += "p{color:#666;line-height:1.6;}";
    html += ".status{background:#e8f5e8;padding:15px;border-radius:5px;margin:20px 0;}";
    html += "</style></head><body>";
    html += "<div class='container'>";
    html += "<h1>🕐 Circular Clock Configuration</h1>";
    html += "<div class='status'>✅ Successfully connected to Circular Clock!</div>";
    html += "<p>Your iOS device is now connected and the captive portal has been validated.</p>";
    html += "<p>You can now configure your Circular Clock settings or close this page.</p>";
    html += "<p><strong>Network:</strong> CircularClockAP<br>";
    html += "<strong>Status:</strong> Connected and Validated</p>";
    html += "</div></body></html>";
    request->send(200, "text/html", html);
  });
  
  // Catch-all handler for captive portal
  server.onNotFound([](AsyncWebServerRequest *request){
    Serial.println("Redirect from: " + request->url());
    // For unknown URLs, redirect to main page
    request->redirect("http://192.168.4.1/");
  });
  
  // Start the server.
  server.begin();
  Serial.println("Web server started.");
  Serial.println("--- Setup Complete ---");
}

void loop() {
  // Process DNS requests for captive portal
  dnsServer.processNextRequest();
  
  // Monitor connected devices every 10 seconds
  static unsigned long lastCheck = 0;
  if (millis() - lastCheck > 10000) { // Every 10 seconds
    uint8_t stationCount = WiFi.softAPgetStationNum();
    Serial.printf("AP Status - Connected devices: %d\n", stationCount);
    if (stationCount > 0) {
      Serial.println("iOS device connected successfully!");
    }
    lastCheck = millis();
  }
  
  // The Async libraries handle requests in the background.
  // The loop processes DNS requests and monitors connections.
}

1 Answer 1

0

Downgrade to ESP8266 Arduino core version 3.1.2 or if you are using PlatformIO: platform = [email protected]

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.