esp01s web配网、秘钥、OTA,eeprom,汉字wifi名称,断网重启-Arduino中文社区 - Powered by Discuz! Archiver

jsls071 发表于 2021-11-25 16:20

esp01s web配网、秘钥、OTA,eeprom,汉字wifi名称,断网重启

实现的功能
web配网,web配秘钥。利用wifimanager 库,可以搜索想用的wifi,自己填密码
用EEPROM储存通过网页设置的秘钥,这个貌似是blinker 专属设备的功能
webOTA
同步不同方式对开关操作后,开关状态
汉字wifi名称,即,在路由器中显示的汉字名称
长时间断网重启,因为设置了多个wifi,且wifi名称也能引导程序配网

注意:ide务必使用我的附件,因为有些库被我进行了改动
安装
1.打开8266_package_3.0.1_arduino.cn
2.打开Arduino IDE菜单 > 文件 >首选项,在 附加开发板管理器网址 输入框中,填入以下网址:
https://www.arduino.cn/package_esp8266com_index.json

使用ide串口监视器方式:插入usb,然后打开ide串口监视器,如很快出现窗口,关闭重新打开

使用说明1. 重新配网方式:   实体按钮长按4s以上,进入配网    搜索到这个wifi热点"cxpw"   app按钮长按浏览器访问8266的IP地址 进入网页选择    2. 更改路由器显示的名称   就是增加一个传值的函数,把自定义名称传给BlinkerMQTT 找到libraries\blinker-library-dev_3.0\src\Adapters\BlinkerMQTT.h①在 class BlinkerMQTT 外部 增加全局变量 String _hostname2 ; ②在 class BlinkerMQTT 内部 public 中增加函数 void hostname2(const String _name2); ③在void BlinkerMQTT::connectWiFi(const char* _ssid, const char* _pswd)上部增加void BlinkerMQTT::hostname2(const String _name2){    _hostname2 = BLINKER_F("智能_");    _hostname2 +=_name2;}④在内部改为 String _hostname = _hostname2;   其他_hostname =注释掉 如果不用传值函数,可只改④如汉字显示乱码,.h文件另存编码必须选择ANSI格式 3.所有指令统一进入控制函数 4.程序预设多个wifi账号信息,利用wifiscan,方便调试查看及日常使用。 5.webOTA如内存太小,如01s只有1M,编译或上传时 把flah size 设置成 no spiffs   或者fs:none OTA:502k 。此设置带来问题:程序不能用spiff先进入ota上传一个最小的bin(只有webota功能),再进入webota,上传准备使用的bin。进入ip地址也可以选择升级,不必记住IP地址后面加/update的方式。经常忘记 6.重启方式APP 发送cq访问IP地址 选择重启 二,问题1.不确定WiFiManager.h 或blinker 调用了json库,用过一次json没成功2.pulseIn();取按钮按下时间的函数,不能用 01s 引脚TX=1 RX=3GPIO0通电时接地为烧录模式
以下主程序,记着改wifi信息 和 秘钥#define BLINKER_WIFI                  //接入方式:wifi
#define BLINKER_ALIGENIE_OUTLET         //接入天猫插座库
#define BLINKER_PRINT Serial            //串口协议库
#include <WiFiManager.h>                //wifimanager库
#include <Blinker.h>                  //官方库
#define BLINKER_WITHOUT_SSL //非SSL加密通信接入,省堆栈,不是必要的

#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
ESP8266WebServer httpServer(80);   //webota
ESP8266HTTPUpdateServer httpUpdater;//webota

String devname = "DT";   //定义WIFI名称和主机名,只能非汉字,显示"智能_"+devname
char auth[] = "0b436cf***";//换成你的,也可配网时再填
int led= 2;      //板载led。不做为指示灯时,随可便定义
int relay = 0; //继电器连接在8266的GPIO0上,LOW时打开
bool zt = LOW ; //继电器连接在8266的GPIO0上,LOW时打开;

void(*resetFunc) (void) = 0;//据说软复位resetFunc();
int key = 1; //本地开关,与gnd接通时动作
BlinkerMQTTBlinkerMQTT2;

struct storeStruct_t {
char myVersion;
char name;
};
charversion2 = "186"; // 保存数据用验证码

char api_key = ""; //增加网页设置页面参数,网页保存秘钥
char mqtt_server; //增加网页设置页面参数,预留传值

char cxpw[] = "cxpw";//搜到这个wifi重新配网,手机开热点尽量靠近
char ssid[] = "xxxx";            //默认wifi-1,改成你的
char pswd[] = "123123123";      
char ssid2[] = "CMCC-2dvu";    //默认wifi-2,改成你的
char pswd2[] = "ms8888";   

//*******新建组件对象
BlinkerButton Button1("btn-abc");    //设置app按键的键名
BlinkerText Text1("tex-zh4");       //绑定文字组件
BlinkerText Text2("tex-vkh");

//*******天猫精灵
void aligeniePowerState(const String & state)
{
BLINKER_LOG("天猫精灵语音操作!");            //串口打印
show(state);          //没测试,不知道 state 内容
if (state == BLINKER_CMD_ON) {
    BlinkerAliGenie.powerState("on");
    BlinkerAliGenie.print();
}
else if (state == BLINKER_CMD_OFF) {
    BlinkerAliGenie.powerState("off");
    BlinkerAliGenie.print();
}
Text2.print("天猫");
}

void aligenieQuery(int32_t queryCode)      //天猫设备查询的回调函数
{
BLINKER_LOG("AliGenie Query codes: ", queryCode);
switch (queryCode)
{
    case BLINKER_CMD_QUERY_ALL_NUMBER :
      BLINKER_LOG("AliGenie Query All");

      BlinkerAliGenie.powerState(relay ? "on" : "off");
      BlinkerAliGenie.print();
      break;
    case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
      BLINKER_LOG("AliGenie Query Power State");
      BlinkerAliGenie.powerState(relay ? "on" : "off");
      BlinkerAliGenie.print();
    default :
      BlinkerAliGenie.powerState(relay ? "on" : "off");
      BlinkerAliGenie.print();
      break;
}
}

//APP未绑定的组件被触发,或者输入框发送内容,执行其中内容
void dataRead(const String & data)
{
show(data);
}
//App 按键
void button1_callback(const String & state)      //app里按键有2种模式3钟不同样式用state来存储组键的值按键 : "tap"(点按); "pre"(长按); "pup"(释放)开关 : "on"(打开); "off"(关闭)
{
show(state);
}
//App定时向设备发送心跳包, 收到心跳包后执行
void heartbeat()
{
show("chaxun");   
}
//APP“所有设备”页显示开关按钮
void switch_callback(const String & state)
{
show(state);
}
//本地开关控制2
int jilu = 0 ;
int startPressed = 0 ;
void sdms() {
if (digitalRead(key) == LOW)
{ jilu = millis() - startPressed; //计算按下的时间
}
else
{ startPressed = millis();

    if (jilu > 30 && jilu < 1300)
    {
      digitalWrite(relay, !digitalRead(relay));
      show("tongbu");   //同步
      Text2.print("本地开关");
    }
    else if (jilu > 4000)
    {
      show("press");
    }

    jilu = 0;
}
}

void setup()
{
delay(3000);
Serial.begin(115200);   // 初始化串口
delay(200);
pinMode(relay, OUTPUT);
pinMode(led, OUTPUT);       //设为输出,闪灯
show("off");      //初始上电关
delay(200);
BLINKER_DEBUG.stream(Serial);//查看设备端调试信息
BLINKER_DEBUG.debugAll();          //查看设备端调试信息
delay(100);
lianwang();       //进入联网程序
Blinker.delay(300);
Button1.attach(button1_callback);      //app按键回调
Blinker.attachData(dataRead);             //没有绑定的控件 函数注册
Blinker.attachHeartbeat(heartbeat);         //app定时向设备发送心跳包, 设备收到心跳包后会返回设备当前状态进行语音操作和app操作同步。
BUILTIN_SWITCH.attach(switch_callback);    //注册APP设备外面的图标上显示这一个开关按键
BlinkerAliGenie.attachPowerState(aligeniePowerState);      //天猫语音操作注册函数
BlinkerAliGenie.attachQuery(aligenieQuery);//天猫设备查询的回调函数
httpUpdater.setup(&httpServer);//OTA
httpServer.begin();      //OTA
httpServer.on("/", homepage);//访问主页

// 初始化IO
    digitalWrite(led, HIGH);
pinMode(key, INPUT_PULLUP);       //设输入上拉,按钮控制
}

void loop() {
Blinker.run();
sdms();//本地开关
cq();//无网重启
httpServer.handleClient();//OTA
}

const char PAGE_INDEX[] PROGMEM = R"(
<!DOCTYPE html ">
<html">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>ESP8266物联网</title>
</head>

<body>
<h1>ESP8266物联网</h1>
<p>你正在浏览ESP8266提供的信息</p>
<p>
    <a href="/update" target="_self" title="升级">升级</a><br/>
</p>
<p>
    <a href="/?pw=abc" target="_self" title="重新设置">重新设置</a><br/>
</p>
<p>
    <a href="/?cq=abc" target="_self" title="重新启动">重新启动</a><br/>
</p>
</body>
</html>
)";
// 设置主页请求处理函数
void homepage() {
httpServer.send(200,"text/html",PAGE_INDEX);
Blinker.println("用户访问了主页");

    if (httpServer.hasArg("pw")) {
    Serial.print("请求中pw参数的值:");
    //Serial.println(httpServer.arg("token"));
show("press");
}
      if (httpServer.hasArg("cq")) {
show("cq");
}
else {
    Serial.println("当前请求中无法找到指定请求体内容");
}
}


//使用web配置网络
void WebConfig() {
httpServer.stop();
WiFiManager wifiManager;


for (int counter = 1; counter <= 4; counter++) { //闪灯提示进入配网
   digitalWrite(led, HIGH);
    Blinker.delay(300);
    digitalWrite(led, LOW);
    Blinker.delay(300);
}

wifiManager.resetSettings();
      
//设置配置页增加两个参数
WiFiManagerParameter custom_apikey("apikey", "apikey", api_key, 32);
WiFiManagerParameter custom_mqtt_server("server", "server", mqtt_server, 40);
wifiManager.addParameter(&custom_apikey);
wifiManager.addParameter(&custom_mqtt_server);
/*************************************/
/*** 步骤三:尝试连接网络,失败去到配置页面 **/
Serial.println("Entered config mode...");

// wifiManager.setConfigPortalTimeout(60);//设置连接超时时间60s
wifiManager.setMinimumSignalQuality(40);   //过滤信号质量

char buf[]="";
devname="智能_"+devname ;
strcpy(buf,devname.c_str());
wifiManager.startConfigPortal(buf, NULL);//直接进入配网管理,不会尝试保存的wifi
//wifiManager.autoConnect(buf, NULL);
Serial.print("ESP8266 Connected to ");
/*************************************/
// 读取配置页面配置好的信息
strcpy(mqtt_server, custom_mqtt_server.getValue());
strcpy(api_key,custom_apikey.getValue() );
saveinf1(api_key);
delay(100);
//ESP.restart();
resetFunc();
}

void show(const String & state) {
    if (state.endsWith("on") == 1 ){
    digitalWrite(relay, zt);   
}
if (state.endsWith("off") == 1 ){
    digitalWrite(relay, !zt);
}
    if (state.endsWith("tap") == 1 ){
      digitalWrite(relay, zt);
      Blinker.delay(3000);
    digitalWrite(relay, !zt);
   Text2.print("电梯");
}
if(state == "press") {
Text2.print("重新配网");
WebConfig();
return;
}
if(state.endsWith("cq") == 1 ) {
Text2.print("重新启动");
Blinker.delay(200);
ESP.restart();
}
      Blinker.delay(200);
      if (digitalRead(relay) == zt)
      {
         digitalWrite(led, LOW);
      BUILTIN_SWITCH.print("on");
      Button1.color("red");            //设置app按键是红色
      Button1.text("继电器打开");
      Button1.print("on");   
    }
      else
      {
            digitalWrite(led, HIGH);
      BUILTIN_SWITCH.print("off");
      Button1.color("gray");            //设置app按键是灰色
      Button1.text("继电器关闭");
      Button1.print("off");      
      }
      Text1.print(WiFi.localIP().toString().c_str(),WiFi.SSID().c_str());//上传IP地址和wifi名称
}

void saveinf1( String api_key1) {      //保存api
Serial.print("saved:");
storeStruct_t saved;

strcpy(saved.name,api_key1.c_str());
strcpy(saved.myVersion,version2);//验证码赋值

EEPROM.begin(4095);
EEPROM.put( 1, saved );
   Blinker.delay(300);
EEPROM.commit();                      // Only needed for ESP8266 to get data written
EEPROM.end();                         // Free RAM copy of structure
}

void loadConfig() {
// Loads configuration from EEPROM into RAM
Serial.println("Loading config");
storeStruct_t load;
EEPROM.begin(4095);
EEPROM.get( 1, load);
EEPROM.end();

if (load.myVersion != version2 ||
      load.myVersion != version2 ||
   load.myVersion != version2)   //比较验证码
{
    Serial.println("验证码没通过");   
    return;
}
else {
    strcpy(auth, load.name);
//给auth,重新赋值
Serial.println(auth); }
}

void lianwang(){

BlinkerMQTT2.hostname2(devname);//BlinkerMQTT文件修改后才能用
digitalWrite(led, LOW); //常亮联网
//配网保存的信息
loadConfig(); //读auth的值
       Blinker.delay(300);      
int n = WiFi.scanNetworks();    //开始同步扫描,存放在变量n中
    for (int i = 0; i < n; ++i){//开始逐个打印扫描到的wifi
      Serial.print(WiFi.SSID(i));
      if (WiFi.SSID(i)==cxpw )//扫描到进入网页配网
      {
         Serial.println("重新配网");
      WebConfig();
      }
   if(WiFi.SSID(i)==ssid )
   {
       Blinker.begin(auth, ssid, pswd);
   return;
      }
         if(WiFi.SSID(i)==ssid2 )
   {
       Blinker.begin(auth, ssid2, pswd2);
   return;
      }
         if(WiFi.SSID(i)==WiFi.SSID().c_str() )
   {
      Blinker.begin(auth, WiFi.SSID().c_str(), WiFi.psk().c_str());
   return;
      }
    }   
       Serial.println("没找到网络3s后重试!");   
    delay(3000);   
lianwang();
}
int detect_os_time=60;
void cq(){    //设定断网重新启动
         bool result = Blinker.connected();         //获取连接服务器的状态0失败 1成功
       if (result == 1|| detect_os_time-millis()/60000 >60) {   //   或语句是防止millis()溢出时不能进入倒计时
      detect_os_time =60+ millis()/60000;}//倒计时60分钟
      else
      {       if (millis()%60000==0) {//每分钟提醒一次
                         Serial.print("断网重启倒计时(分钟):");
                        Serial.println(detect_os_time-millis()/60000 );
                     Blinker.delay(300);
                        }

if (detect_os_time-millis()/60000 <=0 && digitalRead(relay) != zt) {   //超时且开关关闭时 重启
                         //ESP.restart();
                         resetFunc();
                              }
       }
      }
以下是ota程序,我已经尽量减小了,但是水平有限。#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>

ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;

void setup(void) {

Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin("xxxx", "123123123");

while (WiFi.status() != WL_CONNECTED) {
      Serial.print("Connecting...");
    delay(400);
}

httpUpdater.setup(&httpServer);
httpServer.begin();
httpServer.on("/", homepage);//访问主页,不用记IP地址+/update 的升级方式

Serial.print("Open http://");
Serial.print(WiFi.localIP());
Serial.println("/update in your browser");
}

void loop(void)
{
httpServer.handleClient();
}
const char PAGE_INDEX[] PROGMEM = R"(
<!DOCTYPE html ">
<html">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>ESP8266物联网</title>
</head>

<body>
<h1>ESP8266物联网</h1>
<p>你正在浏览ESP8266提供的信息</p>
<p>
    <a href="/update" target="_self" title="升级">升级</a><br/>
</p>

</body>
</html>
)";
// 设置主页请求处理函数
void homepage() {
httpServer.send(200,"text/html",PAGE_INDEX);
Serial.println("用户访问了主页");
}
APP界面配置{¨config¨{¨headerColor¨¨transparent¨¨headerStyle¨¨dark¨¨background¨{¨img¨¨assets/img/bg/f3.jpg¨¨isFull¨»}}¨dashboard¨|{¨type¨¨btn¨¨ico¨¨fad fa-siren-on¨¨mode¨Ê¨t0¨¨点我开关灯¨¨clr¨¨#389BEE¨¨t1¨¨文本2¨¨bg¨É¨cols¨Ë¨rows¨Ë¨key¨¨btn-abc¨´x´Ï´y´Ë¨speech¨|÷¨lstyle¨Ê}{ßA¨deb¨ßEÉßLÉßMÑßNÍßO¨debug¨´x´É´y´ÏßQ|÷ßRÊ}{ßA¨tex¨ßF¨文本1¨ßJßKßLÊßC¨fad fa-arrow-alt-up¨ßMÍßNËßO¨tex-zh4¨´x´É´y´ËßQ|÷ßRÌ}{ßAßUßF¨1234¨ßJßKßLÉßC´´ßMËßNÊßO¨tex-vkh¨´x´Ï´y´ÍßQ|÷ßRÉ}{ßA¨inp¨ßLÉßMÑßNËßO¨inp-27v¨´x´É´y´¤AßQ|÷}÷¨actions¨|¦¨cmd¨¦¨switch¨‡¨text¨‡¨on¨¨打开?name¨¨off¨¨关闭?name¨—÷¨triggers¨|{¨source¨ße¨source_zh¨¨开关状态¨¨state¨|ßgßi÷¨state_zh¨|¨打开¨¨关闭¨÷}÷}
arduino及8266_package下载链接:https://pan.baidu.com/s/1tNotiyqCPmEZ2og3a5v0FQ 提取码:1234

weiqinglong51 发表于 2021-11-26 16:03

学习了,谢谢分享

alonemars 发表于 2021-11-26 16:57

感谢分享代码。

njbhqm 发表于 2021-12-3 08:26

注意:ide务必使用我的附件,因为有些库被我进行了改动
这个IDE使用后电脑崩溃,结果全部不能编译了,换原来的也不行

jsls071 发表于 2021-12-9 09:33

njbhqm 发表于 2021-12-3 08:26
注意:ide务必使用我的附件,因为有些库被我进行了改动
这个IDE使用后电脑崩溃,结果全部不能编译了,换原 ...
用自己的也行 以为有些库我改了,你照着报错,把相关程序删掉,应该也可以用。或者把相关的库用我的替换

dj_wuxin 发表于 2022-1-14 02:17

学习一下···
·

许普查 发表于 2022-2-23 10:06

楼主怎么修改呢

yunqi 发表于 2022-4-27 14:01

看不懂,好难。
请问主程序、ota程序两个程序,怎么刷入8266?不太懂,我就知道用Arduino上传。
页: [1]
查看完整版本: esp01s web配网、秘钥、OTA,eeprom,汉字wifi名称,断网重启