Hey, I have a solution that works pretty well for me, as it only acts as a range extender. Basically on initial boot it wipes the EEPROM (Only the needed addresses, because I know we have limited writes to the EEPROM) and sets a default SSID and Password for both the Station and AP (you can configure it in the program before you upload). Afterwards it simply reads the SSID and Password from the set addresses in the EEPROM and uses that. I can just connect to the AP and visit it's local IP and change the SSID and Password of either the Station or AP there.
A copy of my code is below. I am very new to C programming, so my code may be a little obfuscated and any improvements suggested will be much appreciated.
Edit: Made some improvements to my code. Added a pic of the configuration page.
Code: Select all// NAPT example released to public domain
#if LWIP_FEATURES && !LWIP_IPV6
#define HAVE_NETDUMP 0
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <lwip/napt.h>
#include <lwip/dns.h>
#include <LwipDhcpServer.h>
#include <EEPROM.h>
#define NAPT 1000
#define NAPT_PORT 10
#if HAVE_NETDUMP
#include <NetDump.h>
void dump(int netif_idx, const char* data, size_t len, int out, int success) {
(void)success;
Serial.print(out ? F("out ") : F(" in "));
Serial.printf("%d ", netif_idx);
// optional filter example: if (netDump_is_ARP(data))
{
netDump(Serial, data, len);
//netDumpHex(Serial, data, len);
}
}
#endif
//Additional Functions
void firstboot(void) {
Serial.println("Wiping EEPROM Addresses < 193...");
for (int i = 0; i < 193; i++) {
EEPROM.write(i, 0);
}
Serial.println("Setting up WiFi and AP...");
String stassid = "Digicel_WiFi_M4cK";
for (int i = 0; i < stassid.length(); i++) {
EEPROM.write(i, stassid[i]);
Serial.println("Wrote: " + stassid[i]);
}
String stapsk = "B3hY6t4Y";
for (int i = 0; i < stapsk.length(); i++) {
EEPROM.write(32 + i, stapsk[i]);
Serial.println("Wrote: " + stapsk[i]);
}
String apssid = "My Hotspot";
for (int i = 0; i < apssid.length(); i++) {
EEPROM.write(96 + i, apssid[i]);
Serial.println("Wrote: " + apssid[i]);
}
String appsk = "1234567890";
for (int i = 0; i < appsk.length(); i++) {
EEPROM.write(128 + i, appsk[i]);
Serial.println("Wrote: " + appsk[i]);
}
EEPROM.commit();
delay(500);
ESP.reset();
}
String netcreds (int x, int y) {
// STASSID at Address 0-31 (32 characters max)
// STAPSK at Address 32-95 (63 characters max)
// APSSID at Address 96-127
// APPSK at Address 128-191
String cred = "";
for (int i = x; i < y; i++) {
cred += char(EEPROM.read(i));
}
return cred;
}
bool testwifi() {
int count = 0;
while (count < 20) {
if (WiFi.status() == WL_CONNECTED) {
Serial.printf("WiFi Connected! \nSTA: %s (dns: %s / %s)\n",
WiFi.localIP().toString().c_str(),
WiFi.dnsIP(0).toString().c_str(),
WiFi.dnsIP(1).toString().c_str());
// give DNS servers to AP side
dhcpSoftAP.dhcps_set_dns(0, WiFi.dnsIP(0));
dhcpSoftAP.dhcps_set_dns(1, WiFi.dnsIP(1));
return true;
}
Serial.print(".");
delay(1000);
count++;
}
Serial.println("\nCan't connect to WiFi, connect to AP and configure...");
return false;
}
// Server Stuff
ESP8266WebServer server(80);
String content;
void setup() {
Serial.begin(230400);
EEPROM.begin(512);
pinMode(2, OUTPUT);
digitalWrite(2, HIGH);
delay(1000);
Serial.println("Setting Radio Type to N");
WiFi.setPhyMode(WIFI_PHY_MODE_11N);
Serial.printf("\n\nNAPT Range extender\n");
Serial.printf("Heap on start: %d\n", ESP.getFreeHeap());
if (EEPROM.read(192) != 0) {
Serial.println("It seems that this is a fresh device... configuring");
delay(2000);
firstboot();
}
#if HAVE_NETDUMP
phy_capture = dump;
#endif
// first, connect to STA so we can get a proper local DNS server
char *STASSID = strdup(netcreds(0, 32).c_str());
char *STAPSK = strdup(netcreds(32, 96).c_str());
WiFi.mode(WIFI_STA);
Serial.printf("Attempting to connect to '%s' using password '%s'\n", STASSID, STAPSK);
WiFi.begin(STASSID, STAPSK);
testwifi();
WiFi.softAPConfig( // enable AP, with android-compatible google domain
IPAddress(192, 168, 4, 1),
IPAddress(192, 168, 4, 1),
IPAddress(255, 255, 255, 0));
char *APSSID = strdup(netcreds(96, 128).c_str());
char *APPSK = strdup(netcreds(128, 192).c_str());
WiFi.softAP(APSSID, APPSK);
Serial.printf("AP: %s\n", WiFi.softAPIP().toString().c_str());
Serial.printf("Heap before: %d\n", ESP.getFreeHeap());
err_t ret = ip_napt_init(NAPT, NAPT_PORT);
Serial.printf("ip_napt_init(%d,%d): ret=%d (OK=%d)\n", NAPT, NAPT_PORT, (int)ret, (int)ERR_OK);
if (ret == ERR_OK) {
ret = ip_napt_enable_no(SOFTAP_IF, 1);
Serial.printf("ip_napt_enable_no(SOFTAP_IF): ret=%d (OK=%d)\n", (int)ret, (int)ERR_OK);
if (ret == ERR_OK) {
Serial.printf("WiFi Network '%s' with Password '%s' is now setup.", APSSID, APPSK);
}
}
Serial.printf("\nHeap after napt init: %d\n", ESP.getFreeHeap());
if (ret != ERR_OK) {
Serial.printf("NAPT initialization failed\n");
}
// Server Config
server.begin();
server.on("/", []() {
char *STASSID = strdup(netcreds(0, 32).c_str());
char *APSSID = strdup(netcreds(96, 128).c_str());
char *APPSK = strdup(netcreds(128, 192).c_str());
content = "<!DOCTYPE html><html lang='en'><meta name='viewport' content='width=device-width, initial-scale=1.0'>";
content += "<head><title>ESP8266 Configuration Page</title></head>";
content += "<body>";
content += "<h1>Wireless Station Settings</h2>";
content += "<form method='get' action='stasettings'>";
content += "<label>SSID:</label><br><input name='stassid' placeholder='";
content += STASSID;
content += "' length=32><br>";
content += "<label>Password:</label><br><input type='password' placeholder='********' name='stapsk' length=63><br><small>Must be at least 8 characters or blank!</small><br>";
content += "<br><input type='submit'>";
content += "</form>";
content += "<h1>Wireless Access Point Settings</h2>";
content += "<form method='get' action='apsettings'>";
content += "<label>SSID:</label><br><input name='apssid' placeholder='";
content += APSSID;
content += "' length=32><br>";
content += "<label>Password:</label><br><input type='password' placeholder='";
content += APPSK;
content += "' name='appsk' length=63><br><small>Must be at least 8 characters or blank!</small><br>";
content += "<br><input type='submit'>";
content += "</form>";
content += "<h1>Miscellaneous</h1>";
content += "<form method='get' action='reboot'><input type='submit' value='Reboot'></form>";
content += "<form method='get' action='reset'><input type='submit' value='Factory Reset'></form>";
content += "<br><small>*Factory Reset changes the STA and AP settings to initial values set before code upload</small>";
server.send(200, "text/html", content);
});
server.onNotFound([]() {
server.send(404, "text/plain", "How the heck did you get here?");
});
server.on("/stasettings", []() {
String stassid = server.arg("stassid");
String stapsk = server.arg("stapsk");
if (stassid.length() > 0) {
Serial.println("Clearing EEPROM Addresses");
for (int i = 0; i < 96; i++) {
EEPROM.write(i, 0);
}
Serial.printf("New STA SSID: ");
Serial.println(stassid);
Serial.printf("New STA PASS: ");
Serial.println(stapsk);
Serial.println("Writing new credentials");
for (int i = 0; i < stassid.length(); ++i) {
EEPROM.write(i, stassid[i]);
Serial.print("Wrote: ");
Serial.println(stassid[i]);
}
for (int i = 0; i < stapsk.length(); ++i) {
EEPROM.write(32 + i, stapsk[i]);
Serial.print("Wrote: ");
Serial.println(stapsk[i]);
}
EEPROM.commit();
server.send(200, "text/plain", "Done! Rebooting...");
delay(5000);
ESP.reset();
}
else {
server.send(404);
}
});
server.on("/apsettings", []() {
String apssid = server.arg("apssid");
String appsk = server.arg("appsk");
if (apssid.length() > 0) {
Serial.println("Clearing EEPROM Addresses");
for (int i = 96; i < 192; i++) {
EEPROM.write(i, 0);
}
Serial.printf("New AP SSID: ");
Serial.println(apssid);
Serial.printf("New AP PASS: ");
Serial.println(appsk);
Serial.println("Writing new credentials");
for (int i = 0; i < apssid.length(); ++i) {
EEPROM.write(96 + i, apssid[i]);
Serial.print("Wrote: ");
Serial.println(apssid[i]);
}
for (int i = 0; i < appsk.length(); ++i) {
EEPROM.write(128 + i, appsk[i]);
Serial.print("Wrote: ");
Serial.println(appsk[i]);
}
EEPROM.commit();
server.send(200, "text/plain", "Done! Rebooting...");
delay(5000);
ESP.reset();
}
else {
server.send(404);
}
});
server.on("/reboot", []() {
server.send(200, "text/plain", "Rebooting now...");
delay(5000);
ESP.reset();
});
server.on("/reset", []() {
server.send(200, "text/plain", "Resetting to default...");
EEPROM.write(192, 1);
EEPROM.commit();
delay(5000);
ESP.reset();
});
}
#else
void setup() {
Serial.begin(115200);
Serial.printf("\n\nNAPT not supported in this configuration\n");
}
#endif
void loop() {
server.handleClient();
if (WiFi.status() != WL_CONNECTED) {
digitalWrite(2, LOW);
delay(1000);
digitalWrite(2, HIGH);
delay(1000);
}
else {
digitalWrite(2, HIGH);
}
}