PlatformIO编译通过的库版本
- Blynk:0.6.1
- ArduinoJson:5.13.4
- WifiManager:0.14
- ESP8266:2.0.4、2.1.1、2.2.0
ArduinoIDE编译通过的库版本
- Blynk:0.6.1
- ArduinoJson:5.13.5
- WifiManager:0.14.0
- ESP8266:2.5.1
文中实测的开发板
- WeMos D1 mini
- NodeMCU V2/V3
实现功能
- 可选SSID和输入TOKEN
- 支持OTA
- 不需要每次做一个设备就在代码里输入一次key
需要的材料
APP端先要设置的插件
- V0-文本框插件
- V1-文本框插件
- V2-文本框插件
- V3-虚拟LED插件
附注
- 操作流程
- 重置(刚上传完代码的设备最好先重置一遍):按住按钮 > 按一下RST(第一次操作最好留意串口信息我都写了的) > 设备会重启 > 出现设备热点
- 配置:进入设备WIFI热点 > 输入SSID/密码/KEY > 点击SAVE > 等待连接成功(留意串口是否已经连接到BLYNK)
示例代码(点击代码框内左上角三个点显示全屏模式)
#define BLYNK_PRINT Serial //必须放到第一行
#define BLYNK_DEBUG
#include <Arduino.h> //在PlatformIO需要
#include <FS.h> //如果不正常就放到第二位
#include <BlynkSimpleEsp8266.h>
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
#include <ESP8266mDNS.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson
const int ResetButton = D1; //用于重置的按钮引脚,因应高低电平自行修好下面的代码
const int LEDButton = D2; //用于点亮虚拟LED的按钮引脚,因应高低电平自行修好下面的代码
WidgetLED led3(V3); //虚拟LED插件
int ResetButtonState = digitalRead(ResetButton);
//这里声明"参数"的预设值, 如果和值不同,则会将他们覆盖,这里可以预先把KEY填好,每次重置后都会预先输入KEY,按需要改
char blynk_token[34] = "";
//用于保存数据的标志
bool shouldSaveConfig = false;
boolean LEDbtnState = false;
BlynkTimer timer;
void buttonLedWidget()
{
// 读取按钮引脚
boolean isPressed = (digitalRead(LEDButton) == HIGH);
// 如果值有变化
if (isPressed != LEDbtnState) {
if (isPressed) {
led3.on();
} else {
led3.off();
}
LEDbtnState = isPressed;
}
}
//回调通知我们需要保存配置
void saveConfigCallback ()
{
Serial.println("Should save config");
shouldSaveConfig = true;
}
void setup() {
Serial.begin(115200);
pinMode(ResetButton,INPUT);
pinMode(LEDButton,INPUT);
//读取FS json的配置
Serial.println("mounting FS...");
if (SPIFFS.begin()) {
Serial.println("mounted file system");
if (SPIFFS.exists("/config.json")) {
//文件存在,读取和加载
Serial.println("reading config file");
File configFile = SPIFFS.open("/config.json", "r");
if (configFile) {
Serial.println("opened config file");
size_t size = configFile.size();
// 分配缓冲区以存储文件的内容。
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());
json.printTo(Serial);
if (json.success()) {
Serial.println("\nparsed json");
strcpy(blynk_token, json["blynk_token"]);
} else {
Serial.println("failed to load json config");
}
configFile.close();
}
}
} else {
Serial.println("failed to mount FS");
}
// 要配置的额外参数(可以是全局的,也可以只是在设置中)
// 连接后,parameter.getValue()将获得配置的值//After connecting, parameter.getValue() will get you the configured value
// id/name placeholder/prompt 的默认长度
WiFiManagerParameter custom_blynk_token("blynk", "blynk token", blynk_token, 32);
//WiFiManager
//本地初始化。一旦业务完成,就没有必要保留它
WiFiManager wifiManager;
//设置配置保存通知回调
wifiManager.setSaveConfigCallback(saveConfigCallback);
//在这里添加所有参数
wifiManager.addParameter(&custom_blynk_token);
//设置重置按钮的功能
if (ResetButtonState == HIGH)
{
Serial.println("Getting Reset ESP Wifi-Setting.......");
delay(1000);
wifiManager.resetSettings();
delay(5000);
Serial.println("Formatting FS......");
delay(1000);
SPIFFS.format();
delay(5000);
Serial.println("Done Reboot In 5 seconds");
delay(5000);
ESP.restart();
}
//获取ssid并传递并尝试连接
//如果它没有连接,它将启动具有指定名称的访问点,"AutoConnectAP",并进入等待配置的阻塞循环
//若写成wifiManager.autoConnect("abc", "12345678"),则设备的AP热点名称为"abc",密码为"12345678",留空则热点名字为ESP_#后四位MAC,无密码.热点名可以输入中文,视乎手机而定,有的手机会显示乱码
if (!wifiManager.autoConnect("AutoConnectAP", "")) {
Serial.println("failed to connect and hit timeout");
delay(3000);
//重置并重试,或者让它深入睡眠
ESP.reset();
delay(5000);
}
//如果已经连接
Serial.println("connected...yeey :)");
//读取更新的参数
strcpy(blynk_token, custom_blynk_token.getValue());
//将自定义参数保存到FS
if (shouldSaveConfig) {
Serial.println("saving config");
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
json["blynk_token"] = blynk_token;
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("failed to open config file for writing");
}
json.printTo(Serial);
json.printTo(configFile);
configFile.close();
//end save
}
Serial.println("local ip");
Serial.println(WiFi.localIP());
//OTA部分
// 默认主机名为:esp8266-[ChipID]可以改中文
ArduinoOTA.setHostname("");
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH) {
type = "sketch";
} else { // U_SPIFFS
type = "filesystem";
}
//注意:如果更新SPIFFS,这将是使用SPIFFS.end()卸载SPIFFS的地方
Serial.println("Start updating " + type);
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) {
Serial.println("Auth Failed");
} else if (error == OTA_BEGIN_ERROR) {
Serial.println("Begin Failed");
} else if (error == OTA_CONNECT_ERROR) {
Serial.println("Connect Failed");
} else if (error == OTA_RECEIVE_ERROR) {
Serial.println("Receive Failed");
} else if (error == OTA_END_ERROR) {
Serial.println("End Failed");
}
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Blynk.config(blynk_token,"yourdomainname",8080);
timer.setInterval(500L, buttonLedWidget);
}
void loop() {
ArduinoOTA.handle();
Blynk.run();
timer.run();
//用于显示网络信息的模块插件,不需要可省略
Blynk.virtualWrite(V0,WiFi.localIP().toString());
Blynk.virtualWrite(V1,WiFi.macAddress());
Blynk.virtualWrite(V2,"RSSI:",WiFi.RSSI()," ","SSID: ",WiFi.SSID());
}