#define BLINKER_PRINT Serial
#define BLINKER_WIFI
#define BLINKER_DUEROS_LIGHT //设置小度灯类库
#define BLINKER_WITHOUT_SSL
#include <Blinker.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <EEPROM.h>
#include <DNSServer.h>
#include <ArduinoOTA.h>
#define LED_PIN 2 // ESP-01S板载LED(GPIO2)
#define EEPROM_SIZE 512
ESP8266WebServer server(80);
bool isConnected = false;
String deviceKey = "";
// EEPROM存储结构
struct Config {
char ssid[32];
char password[64];
char blinkerKey[32];
bool configured;
};
#define STASSID "鸿天乐网络科技公司"
const char* ssid = STASSID;
const char* AP_NAME = "鸿天乐网络科技公司";//wifi名字
//暂时存储wifi账号密码
char sta_auth[32] = {0};
char sta_ssid[32] = {0};
char sta_password[64] = {0};
String GET_AUTH;
String GET_SSID;
String GET_PASSWORD;
byte AUTH_ADDR = 0;
byte SISSD_ADDR = 0;
byte PASSWORD_ADDR = 100;
byte AUTH_NUM = 0;
byte SISSD_NUM = 0;
byte PASSWORD_NUM = 0;
const byte DNS_PORT = 53;//DNS端口号
IPAddress apIP(192, 168, 4, 1);//esp8266-AP-IP地址
DNSServer dnsServer;//创建dnsServer实例
ESP8266WebServer server(80);//创建WebServer
bool LED_Flag = false;
String str = "\
<!DOCTYPE html>\r\n\
<html lang='en'>\r\n\
<head>\r\n\
<meta charset='UTF-8'>\r\n\
<meta name='viewport' content='width=device-width, initial-scale=1.0'>\r\n\
<title>Document</title>\r\n\
<style>\r\n\
body {\r\n\
background-color: rgb(0, 0, 0);\r\n\
}\r\n\
table {\r\n\
width: 350px;\r\n\
height: 400px;\r\n\
margin: 100px auto;\r\n\
border-radius: 30px;\r\n\
background-color: rgb(255, 255, 255);\r\n\
text-align: center;\r\n\
}\r\n\
input {\r\n\
width: 270px;\r\n\
height: 45px;\r\n\
line-height: 45px;\r\n\
border-radius: 30px;\r\n\
text-align: center;\r\n\
background-color: rgb(232, 248, 255);\r\n\
border: rgb(255, 255, 255);\r\n\
}\r\n\
span input {\r\n\
width: 130px;\r\n\
height: 40px;\r\n\
color: #fff;\r\n\
line-height: 40px;\r\n\
background-color: rgb(103, 124, 333);\r\n\
}\r\n\
</style>\r\n\
</head>\r\n\
<body>\r\n\
<table>\r\n\
<tr>\r\n\
<td>\r\n\
<form name='input' action='/' method='POST'>\r\n\
<font size='5'><b>鸿天乐网络科技WIFI配网</b></font><br>\r\n\
<hr align='center' width='270px' size='2px'><br>\r\n\
<input type='text' name='ssid' placeholder='请输入wifi名称'><br><br>\r\n\
<input type='text' name='password' placeholder='请输入wifi密码'><br><br>\r\n\
<input type='text' name='Key' placeholder='请输入Blinker密钥'><br><br>\r\n\
<span>\r\n\
<input type='reset' value='重置'>\r\n\
<input type='submit' value='连接'>\r\n\
</span>\r\n\
</form>\r\n\
</td>\r\n\
</tr>\r\n\
</table>\r\n\
</body>\r\n\
</html>\r\n\
";
//a写入字符串长度,b是起始位,str为要保存的字符串
void set_String(int a,int b,String str){
EEPROM.write(a, str.length());//EEPROM第a位,写入str字符串的长度
//把str所有数据逐个保存在EEPROM
for (int i = 0; i < str.length(); i++){
EEPROM.write(b + i, str[i]);
}
EEPROM.commit();
}
//a位是字符串长度,b是起始位
String get_String(int a, int b){
String data = "";
//从EEPROM中逐个取出每一位的值,并链接
for (int i = 0; i < a; i++){
data += char(EEPROM.read(b + i));
}
return data;
}
/*****************************************************
* 函数名称:handleRoot()
* 函数说明:客户端请求回调函数
* 参数说明:无
******************************************************/
void handleRoot() {
server.send(200, "text/html", str);
}
void handleRootPost() {//Post回调函数
Serial.println("handleRootPost");
if (server.hasArg("ssid")) {//判断是否有账号参数
Serial.print("got ssid:");
strcpy(sta_ssid, server.arg("ssid").c_str());//将账号参数拷贝到sta_ssid中
Serial.println(sta_ssid);
} else {//没有参数
Serial.println("error, not found ssid");
server.send(200, "text/html", "<meta charset='UTF-8'>error, not found ssid");//返回错误页面
return;
}
//密码与账号同理
if (server.hasArg("password")) {
Serial.print("got password:");
strcpy(sta_password, server.arg("password").c_str());
Serial.println(sta_password);
} else {
Serial.println("error, not found password");
server.send(200, "text/html", "<meta charset='UTF-8'>error, not found password");
return;
}
//点灯密匙与账号同理
if (server.hasArg("Key")) {
Serial.print("got Key:");
strcpy(sta_auth, server.arg("Key").c_str());
Serial.println(sta_auth);
} else {
Serial.println("error, not found Key");
server.send(200, "text/html", "<meta charset='UTF-8'>error, not found Key");
return;
}
Blinker.begin(server.arg("Key").c_str(), server.arg("ssid").c_str(), server.arg("password").c_str());
server.send(200, "text/html", "<meta charset='UTF-8'>保存成功");//返回保存成功页面
delay(2000);
//连接wifi
connectNewWifi();
}
void initBasic(void){//初始化基础
Serial.begin(115200);
WiFi.hostname("Smart-ESP8266");//设置ESP8266设备名
}
void initSoftAP(void){//初始化AP模式
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
if(WiFi.softAP(AP_NAME)){
Serial.println("ESP8266 SoftAP is right");
}
}
void initWebServer(void){//初始化WebServer
//server.on("/",handleRoot);
//上面那行必须以下面这种格式去写否则无法强制门户
server.on("/", HTTP_GET, handleRoot);//设置主页回调函数
server.onNotFound(handleRoot);//设置无法响应的http请求的回调函数
server.on("/", HTTP_POST, handleRootPost);//设置Post请求回调函数
server.begin();//启动WebServer
Serial.println("WebServer started!");
}
void initDNS(void){//初始化DNS服务器
if(dnsServer.start(DNS_PORT, "*", apIP)){//判断将所有地址映射到esp8266的ip上是否成功
Serial.println("start dnsserver success.");
}
else Serial.println("start dnsserver failed.");
}
/*****************************************************
* 函数名称:HandleVal()
* 函数说明:对客户端请求返回值处理
* 参数说明:无
******************************************************/
void HandleVal()
{
GET_SSID = server.arg("ssid"); //从JavaScript发送的数据中找ssid的值
GET_PASSWORD = server.arg("password"); //从JavaScript发送的数据中找password的值
GET_AUTH = server.arg("Key");
Serial.printf("234:%s\r\n", GET_SSID.c_str());
Serial.printf("235:%s\r\n", GET_PASSWORD.c_str());
Serial.printf("234:%s\r\n", GET_AUTH.c_str());
WiFi.begin(GET_SSID,GET_PASSWORD);
}
/*****************************************************
* 函数名称:handleNotFound()
* 函数说明:响应失败函数
* 参数说明:无
******************************************************/
void handleNotFound() {
digitalWrite(LED_BUILTIN, 0);
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
digitalWrite(LED_BUILTIN, 1);
}
/*****************************************************
* 函数名称:autoConfig()
* 函数说明:自动连接WiFi函数
* 参数说明:无
* 返回值说明:true:连接成功 false:连接失败
******************************************************/
bool autoConfig()
{
if(EEPROM.read(SISSD_ADDR)!=0)
{
GET_AUTH = get_String(EEPROM.read(AUTH_ADDR),AUTH_ADDR+1);
GET_SSID = get_String(EEPROM.read(SISSD_ADDR),SISSD_ADDR+1);
GET_PASSWORD = get_String(EEPROM.read(PASSWORD_ADDR),PASSWORD_ADDR+1);
Serial.printf("AUTH:%s\r\n", GET_AUTH.c_str());
Serial.printf("SSID:%s\r\n", GET_SSID.c_str());
Serial.printf("PSW:%s\r\n",GET_PASSWORD.c_str());
WiFi.mode(WIFI_STA);
WiFi.begin(GET_SSID,GET_PASSWORD);
for (int i = 0; i < 20; i++)
{
if (WiFi.status() == WL_CONNECTED)
{
WiFi.printDiag(Serial);
return true;
//break;
}
else
{
LED_Flag = !LED_Flag;
if(LED_Flag)
digitalWrite(LED_BUILTIN, HIGH);
else
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
}
}
return false;
//WiFi.printDiag(Serial);
}
/*****************************************************
* 函数名称:htmlConfig()
* 函数说明:web配置WiFi函数
* 参数说明:无
******************************************************/
void connectNewWifi()
{
WiFi.mode(WIFI_STA);//切换为STA模式
WiFi.setAutoConnect(true);//设置自动连接
WiFi.begin();//连接上一次连接成功的wifi
Serial.println("");
Serial.print("Connect to wifi");
int count = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(1500);
count++;
if(count > 10){//如果5秒内没有连上,就开启Web配网 可适当调整这个时间
initSoftAP();
initWebServer();
initDNS();
break;//跳出 防止无限初始化
}
Serial.print(".");
}
Serial.println("");
if(WiFi.status() == WL_CONNECTED){//如果连接上 就输出IP信息 防止未连接上break后会误输出
Serial.println("WIFI Connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());//打印esp8266的IP地址
//server.stop();
}
while(1)
{
server.handleClient();
dnsServer.processNextRequest();
if (WiFi.status() == WL_CONNECTED)
{
AUTH_NUM = GET_AUTH.length();
SISSD_NUM = GET_SSID.length();
PASSWORD_NUM = GET_PASSWORD.length();
EEPROM.write(AUTH_ADDR,AUTH_NUM);
set_String(AUTH_NUM,AUTH_ADDR+1,GET_AUTH);
EEPROM.write(SISSD_ADDR,SISSD_NUM);
set_String(SISSD_NUM,SISSD_ADDR+1,GET_SSID);
EEPROM.write(PASSWORD_ADDR,PASSWORD_NUM);
set_String(PASSWORD_NUM,PASSWORD_ADDR+1,GET_PASSWORD);
server.stop();
break;
}
}
}
// 新建组件对象
BlinkerButton ButtonOn("btn-abc");//按键的名称 开灯
int counter = 0;
int GPIO=0;//定义GPIO口用于控制继电器
// 按下按键即会执行该函数
void button1_callback(const String & state) {
if (state == "on") {
BLINKER_LOG("get button state: 开灯");
Blinker.print("switch", "on");
digitalWrite(GPIO, LOW);
delay(200);
ButtonOn.print("on");
}
if (state == "off") {
BLINKER_LOG("get button state: 关灯");
digitalWrite(GPIO, HIGH);
delay(200);
// 反馈开关状态
ButtonOn.print("off");
}
Blinker.vibrate();
}
// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);
counter++;
}
void duerPowerState(const String & state)
{
BLINKER_LOG("need set power state: ", state);
if (state == BLINKER_CMD_OFF) {
digitalWrite(GPIO, HIGH);
BlinkerDuerOS.powerState("off");
BlinkerDuerOS.print();
}
else if (state == BLINKER_CMD_ON) {
digitalWrite(GPIO, LOW);
BlinkerDuerOS.powerState("on");
BlinkerDuerOS.print();
}
}
void setup(void) {
EEPROM.begin(512);
Serial.begin(115200);
initBasic();
// 初始化有LED的IO
pinMode(GPIO,OUTPUT);
digitalWrite(GPIO,HIGH);//初始化,由于继电器是低电平触发。所以刚开始设为高电平
// 初始化blinker
Blinker.begin(server.arg("Key").c_str(), server.arg("ssid").c_str(), server.arg("password").c_str());
BLINKER_DEBUG.stream(Serial);
BLINKER_DEBUG.debugAll();
Blinker.attachData(dataRead);
ButtonOn.attach(button1_callback);
BlinkerDuerOS.attachPowerState(duerPowerState); //小度语音操作注册函数
if (!autoConfig()){
connectNewWifi();
}
}
void loop(void) {
server.handleClient();
dnsServer.processNextRequest();
Blinker.run();
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
检查错误,增加联网时闪烁,联网后停止。自动保存自动联网。
最新发布