Reputation: 1872
I suspect this is a problem that already has a "stock" solution; I need to deploy an ESP8266 device such that it will be able to connect to a secured local WiFi, but I can't know the credentials at the time the software is embedded on the device. Somehow, I'll need to be able to have the end user, with a regular computer (i.e. one that has a keyboard and screen!) "push" this information into the device. For preference, I'd like them to be able to do this over wireless, but a USB/Serial connection would be possible if it has to be done that way.
I guess I could just "bundle" the entire toolchain and source and have them run a script that prompts for this info, builds and uploads the software over USB. But given the ESP's ability to act as an AP, I can't help thinking there's a better way, and that someone has probably already packaged this!
(I suppose a side question worth asking is whether there might be some kind of peer-peer configuration that would be preferable. I want the ESP to have bidirectional, reliable, (i.e. TCP socket-like) communication with the computer host (it doesn't really need Internet access). But I don't really want anything that might compromise the security of that computer, so sticking with the end-user's regular WiFi seems likely the best option.)
What should I investigate? Or what suggestions does anyone have? Or what keyword search would have found me the answer!?
TIA!
Upvotes: 2
Views: 1177
Reputation: 819
I use the following solution. Assuming you are using the arduino API to program your ESP8266
Set the wifi mode to AP_STA
WiFi.mode(WIFI_AP_STA);
Config the softAP (you can either hardcode the SSID and password or use an config file with a default value)
IPAddress apIP(192, 168, 1, 1); WiFi.mode(WIFI_AP); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); WiFi.softAP(apname, password);
(optional) Using the DNSServer library, you set an DNS server
Using the ESP8266WebServer library, you set an HTTP server
Call the onNotFound method of your server object, passing a closure that searches for the requested file, either on SPIFFs or on SD (or both, should you work with both interfaces) and streams it.
server->onNotFound
(
[&]()
{
if(!handleFileRead(server->uri()))
server->send(404, "text/plain", "FileNotFound");
}
);
server->on("/networks.json", & { String json; int numNetworks, i, j, rssi; StaticJsonBuffer<4096> jsonBuffer; JsonArray& networks = jsonBuffer.createArray(); for(j = 0; j < 10; j++) { numNetworks = WiFi.scanNetworks(); Serial.print(numNetworks); Serial.println(" networks"); for (j=0; j
if (WiFi.encryptionType(j) != 7)
network["auth"] = 0;
else
network["auth"] = 1;
rssi = WiFi.RSSI(j);
if (rssi < -90)
network["signal"] = 1;
else if (rssi < -80)
network["signal"] = 2;
else if (rssi < -70)
network["signal"] = 3;
else if (rssi < -67)
network["signal"] = 4;
else if (rssi < -30)
network["signal"] = 5;
}
}
networks.printTo(json);
server->send(200, "application/json", json);
Serial.println("handleFileRead: /networks.json");
}
);
Call the on method again to expect the configurations:
server->on("/configure", & { //Handler //Add a new line File config; File file = SPIFFS.open("/resp.htm", "r"); SPIFFS.remove(configFile); StaticJsonBuffer<512> jsonBuffer; JsonObject& root = jsonBuffer.createObject(); config = SPIFFS.open(configFile, "w"); // add some backup logic later if (!file) { server->send(404, "text/plain", "File Not Found"); return; }
for (int i = 0; i < server->args(); i++) { root[server->argName(i)] = server->arg(i); if(server->argName(i).equals("ssid")) { root["wifissid"] = server->arg(i); }
if(server->argName(i).equals("password"))
{
root["wifipassword"] = server->arg(i);
}
}
server->streamFile(file, "text/html");
root.printTo(config); file.close(); config.close(); }
You will get a neat configuration file with a JSON that you can use to configure the STA SSID and Password.
configWifi(){
File config;
int filelenght;
int taglen;
int result;
unsigned char mac[6];
char * buffer = NULL;
StaticJsonBuffer<1024> jsonBuffer;
wifiConnection = new WiFiClient();
WiFi.mode(WIFI_STA);
WiFi.macAddress(mac);
hex2str(this->clientid, (char *)mac, 6);
config = SPIFFS.open(configFile, "r");
if (!config)
{
config.close();
return;
}
if (config.size() < 10)
{
config.close();
return;
}
buffer = (char *) calloc(config.size() + 1, 1);
config.readBytes(buffer, config.size());
config.close();
Serial.println(buffer);
JsonObject& root = jsonBuffer.parseObject(buffer);
if (!root.success())
{
config.close();
free(buffer);
return;
}
strcpy(wifi_ssid, root["wifissid"]);
strcpy(wifi_password, root["wifipassword"]);
Serial.print("SSID = ");
Serial.print(wifi_ssid);
Serial.print(" Pass = ");
Serial.println(wifi_password);
WiFi.begin(wifi_ssid, wifi_password);
free(buffer);
Serial.println("initialized");
return;
}
That is it. The user will get an captive page to configure his wifi connection.
Upvotes: 0
Reputation: 2737
The easy way is to use a third party library like WiFiManager: https://github.com/tzapu/WiFiManager
example usage: http://www.instructables.com/id/Avoid-Hard-Coding-WiFi-Credentials-on-Your-ESP8266/
Upvotes: 5