概览
BluFi 是一款基于蓝牙通道的 Wi-Fi 网络配置功能,适用于 ESP32。它通过安全协议将 Wi-Fi 配置和证书传输到 ESP32,然后 ESP32 可基于这些信息连接到 AP 或建立 SoftAP。
用户可按需自定义用于对称加密、非对称加密和校验的算法。这里我们采用 DH 算法进行密钥协商、128-AES 算法用于数据加密、CRC16 算法用于校验和验证。
BluFi 流程
BluFi 配网功能包含配置 SoftAP 和 Station 两部分。
下面以配置 Station 为例说明配置步骤。 BluFi 配网的配置 Station 包含广播、连接、服务发现、协商共享密钥、传输数据、回传连接状态等步骤。
代码
引入相关库文件
#include <WiFi.h>
#include <Preferences.h>
#include "BluetoothSerial.h"
定义变量
String ssids_array[50];
String network_string;
String connected_string;
const char* pref_ssid = "";
const char* pref_pass = "";
String client_wifi_ssid;
String client_wifi_password;
const char* bluetooth_name = "ESP32 BLE";
long start_wifi_millis;
long wifi_timeout = 10000;
bool bluetooth_disconnect = false;
enum wifi_setup_stages { NONE, SCAN_START, SCAN_COMPLETE, SSID_ENTERED, WAIT_PASS, PASS_ENTERED, WAIT_CONNECT, LOGIN_FAILED };
enum wifi_setup_stages wifi_stage = NONE;
BluetoothSerial SerialBT;
Preferences preferences;
WIFI联网函数
bool init_wifi()
{
String temp_pref_ssid = preferences.getString("pref_ssid");
String temp_pref_pass = preferences.getString("pref_pass");
pref_ssid = temp_pref_ssid.c_str();
pref_pass = temp_pref_pass.c_str();
Serial.println(pref_ssid);
Serial.println(pref_pass);
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
WiFi.mode(WIFI_STA);
Serial.println();
Serial.print("Connecting to ");
Serial.println(pref_ssid);
WiFi.begin(pref_ssid, pref_pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (millis() - start_wifi_millis > wifi_timeout) {
WiFi.disconnect(true, true);
return false;
}
}
Serial.println();
Serial.print("ESP32-CAM IP Address: ");
Serial.println(WiFi.localIP());
return true;
}
扫码周围已存在网络
void scan_wifi_networks()
{
WiFi.mode(WIFI_STA);
// WiFi.scanNetworks will return the number of networks found
int n = WiFi.scanNetworks();
if (n == 0) {
SerialBT.println("no networks found");
} else {
SerialBT.println();
SerialBT.print(n);
SerialBT.println(" networks found");
delay(1000);
for (int i = 0; i < n; ++i) {
ssids_array[i + 1] = WiFi.SSID(i);
Serial.print(i + 1);
Serial.print(": ");
Serial.println(ssids_array[i + 1]);
network_string = i + 1;
network_string = network_string + ": " + WiFi.SSID(i) + " (Strength:" + WiFi.RSSI(i) + ")";
SerialBT.println(network_string);
}
wifi_stage = SCAN_COMPLETE;
}
}
回调函数,从蓝牙获取wifi登陆信息
void callback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
{
if (event == ESP_SPP_SRV_OPEN_EVT) {
wifi_stage = SCAN_START;
}
if (event == ESP_SPP_DATA_IND_EVT && wifi_stage == SCAN_COMPLETE) { // data from phone is SSID
int client_wifi_ssid_id = SerialBT.readString().toInt();
client_wifi_ssid = ssids_array[client_wifi_ssid_id];
wifi_stage = SSID_ENTERED;
}
if (event == ESP_SPP_DATA_IND_EVT && wifi_stage == WAIT_PASS) { // data from phone is password
client_wifi_password = SerialBT.readString();
client_wifi_password.trim();
wifi_stage = PASS_ENTERED;
}
}
回调显示已分配IP地址
void callback_show_ip(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
{
if (event == ESP_SPP_SRV_OPEN_EVT) {
SerialBT.print("ESP32 IP: ");
SerialBT.println(WiFi.localIP());
bluetooth_disconnect = true;
}
}
联网完成,断开蓝牙
void disconnect_bluetooth()
{
delay(1000);
Serial.println("BT stopping");
SerialBT.println("Bluetooth disconnecting...");
delay(1000);
SerialBT.flush();
SerialBT.disconnect();
SerialBT.end();
Serial.println("BT stopped");
delay(1000);
bluetooth_disconnect = false;
}
启动程序
void setup()
{
/********************** BluetoothWifi ***************************/
Serial.begin(115200);
Serial.println("Booting...");
preferences.begin("wifi_access", false);
if (!init_wifi()) { // Connect to Wi-Fi fails
SerialBT.register_callback(callback);
} else {
SerialBT.register_callback(callback_show_ip);
}
SerialBT.begin(bluetooth_name);
/********************** 放置你的setup代码,执行一次 ***************************/
Serial.println("Test just once...");
}
循环检测是否需要配网
void loop()
{
/********************** BluetoothWifi ***************************/
if (bluetooth_disconnect)
{
disconnect_bluetooth();
}
switch (wifi__stage)
{
case SCAN_START:
SerialBT.println("Scanning Wi-Fi networks");
Serial.println("Scanning Wi-Fi networks");
scan_wifi_networks();
SerialBT.println("Please enter the number for your Wi-Fi");
wifi_stage = SCAN_COMPLETE;
break;
case SSID_ENTERED:
SerialBT.println("Please enter your Wi-Fi password");
Serial.println("Please enter your Wi-Fi password");
wifi_stage = WAIT_PASS;
break;
case PASS_ENTERED:
SerialBT.println("Please wait for Wi-Fi connection...");
Serial.println("Please wait for Wi_Fi connection...");
wifi_stage = WAIT_CONNECT;
preferences.putString("pref_ssid", client_wifi_ssid);
preferences.putString("pref_pass", client_wifi_password);
if (init_wifi()) { // Connected to WiFi
connected_string = "ESP32 IP: ";
connected_string = connected_string + WiFi.localIP().toString();
SerialBT.println(connected_string);
Serial.println(connected_string);
bluetooth_disconnect = true;
} else { // try again
wifi_stage = LOGIN_FAILED;
}
break;
case LOGIN_FAILED:
SerialBT.println("Wi-Fi connection failed");
Serial.println("Wi-Fi connection failed");
delay(2000);
wifi_stage = SCAN_START;
break;
}
/********************** 放置你的loop代码,重复执行 ***************************/
Serial.println("Test repeat...");
delay(5000);
}
编译好的二进制文件,直接烧录,即可体验。https://download.csdn.net/download/u014331212/85019734