Bootstrap WiFi 凭据进入 ESP8266

Bootstrap WiFi credentials into ESP8266

我怀疑这是一个已经有 "stock" 解决方案的问题;我需要部署一个 ESP8266 设备,以便它能够连接到安全的本地 WiFi,但在软件嵌入到设备上时我不知道凭据。不知何故,我需要能够让最终用户使用普通计算机(即具有键盘和屏幕的计算机!)"push" 将此信息输入设备。作为偏好,我希望他们能够通过无线方式完成此操作,但如果必须以这种方式完成,则 USB/Serial 连接是可能的。

我想我可以 "bundle" 整个工具链和源代码,并让它们 运行 一个提示输入此信息的脚本,通过 USB 构建和上传软件。但是考虑到ESP作为AP的能力,我不禁想到有更好的方法,而且可能已经有人打包了!

(我想一个值得问的附带问题是是否可能有某种更可取的对等配置。我希望 ESP 与计算机主机(它并不真的需要互联网访问)。但我真的不想要任何可能危及该计算机安全的东西,所以坚持使用最终用户的常规 WiFi 似乎是最好的选择。)

我应该调查什么?或者有人有什么建议?或者什么关键字搜索会找到我的答案!?

TIA!

最简单的方法是使用第三方库,如 WiFiManager: https://github.com/tzapu/WiFiManager

用法示例:http://www.instructables.com/id/Avoid-Hard-Coding-WiFi-Credentials-on-Your-ESP8266/

我使用以下解决方案。假设您正在使用 arduino API 对 ESP8266

进行编程
  • 设置wifi模式为AP_STA

    WiFi.mode(WIFI_AP_STA);

  • 配置 softAP(您可以硬编码 SSID 和密码或使用具有默认值的配置文件)

    IP 地址 apIP(192, 168, 1, 1); WiFi.mode(WIFI_AP); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); WiFi.softAP(apname, 密码);

  • (可选)使用 DNSServer 库,您设置一个 DNS 服务器

  • 使用 ESP8266WebServer 库,设置 HTTP 服务器

  • 调用您的服务器对象的 onNotFound 方法,传递一个闭包来搜索请求的文件,无论是在 SPIFF 上还是在 SD 上(或者两者,如果您使用这两个接口)并流式传输它。

    server->onNotFound
      (
        [&]()
        {
          if(!handleFileRead(server->uri()))
            server->send(404, "text/plain", "FileNotFound");
        }
      ); 
    
    • 调用 on 方法,以便它期望一个名为 networks.json 的文件(您可以提供其他名称)。此方法流式传输一个 json 字符串,其中包含所有可用的网络 SSID、信号级别和安全模式。要使用此代码,您应该包含 ArduinoJson 库

    server->on("/networks.json", & { 字符串 json; int numNetworks, i, j, rssi; StaticJsonBuffer<4096> json缓冲区; JsonArray& networks = jsonBuffer.createArray(); 对于(j = 0;j < 10;j++) { numNetworks = WiFi.scanNetworks(); Serial.print(numNetworks); Serial.println("网络"); 对于(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");
    }
    

    );

  • 再次调用on方法期待配置:

    server->on("/配置", & { //处理程序 //添加一个新行 文件配置; 文件 file = SPIFFS.open("/resp.htm", "r"); SPIFFS.remove(配置文件); StaticJsonBuffer<512> json缓冲区; JsonObject&root = jsonBuffer.createObject(); 配置=SPIFFS.open(配置文件,"w"); // 稍后添加一些备份逻辑 如果(!文件) { 服务器->发送(404,"text/plain","File Not Found"); return; }

    for (int i = 0; i < server->args(); i++) { root[server->argName(i)] = server->arg(i); 如果(服务器->argName(i)。等于("ssid")) { root["wifissid"] = server->arg(i); }

    if(server->argName(i).equals("password"))
    {
      root["wifipassword"] = server->arg(i);
    }
    

    }

    server->streamFile(file, "text/html");

    root.printTo(配置); file.close(); config.close(); }

    • 创建一个网页,该网页读取名为 /networks.json 的文件以填充表单中的可用网络列表。当用户选择一个网络时,让页面要求输入密码(我不会为此提供代码,因为实际上有数百万种方法可以做到这一点)。您应该在此页面上使用 javascript。如果你想使用任何花哨的 javascript 插件,例如 jquery、bootstrap 或 angular,你可以使用它,但请记住 ESP8266HttpServer 库可能无法处理较大的文件(我设法将 jquery 压缩到 27kb,并且在这个大小上没有问题)。表单应该 GET 到“/config”。
  • 您将获得一个带有 JSON 的简洁配置文件,您可以使用它来配置 STA SSID 和密码。

    配置Wifi(){ 文件配置; int 文件长度; 内特塔伦; 整数结果; 无符号字符mac[6]; 字符 * 缓冲区 = NULL; StaticJsonBuffer<1024> json缓冲区; wifiConnection = new WiFiClient(); WiFi.mode(WIFI_STA); WiFi.macAddress(mac); hex2str(this->clientid, (char *)mac, 6); 配置=SPIFFS.open(配置文件,"r"); 如果(!配置) { config.close(); return; } 如果 (config.size() < 10) { config.close(); return; }
    缓冲区 = (char *) calloc(config.size() + 1, 1); config.readBytes(缓冲区, config.size()); config.close(); Serial.println(缓冲区); JsonObject& root = jsonBuffer.parseObject(缓冲区); 如果 (!root.success()) { config.close(); 免费(缓冲区); return; } strcpy(wifi_ssid, 根["wifissid"]); strcpy(wifi_password, 根["wifipassword"]); Serial.print("SSID = "); Serial.print(wifi_ssid); Serial.print("通过="); Serial.println(wifi_password); WiFi.begin(wifi_ssid, wifi_password); 免费(缓冲区); Serial.println("initialized");
    return; }

就是这样。用户将获得一个强制页面来配置他的 wifi 连接。