专栏首页嵌入式开发圈ESP8266配网思路(不使用SmartConfig)

ESP8266配网思路(不使用SmartConfig)

这是我之前学习ESP8266想的思路,后续用STM32来实现其中一个或两个功能。

一、ESP8266配网(使用手机APP来给模组配置)

假设已经开发了一个手机APP,这个APP完成的功能如下:

1、连接设备接的模块ESP8266生成的热点

2、给设备热点发送要连接的路由器的名字和密码

配网流程

1、设备让ESP8266进入AP模式设备MCU通过串口给ESP8266发送AT+CWMODE=2,让ESP8266进入AP模式。如果进入AP模式成功,用手机可以搜索到ESP8266模块的热点信息。

2、用手机APP去连接这个热点发送路由器ssid和password,假设格式为: ssid:“xxx”,password:“xxxx”

3、解析APP发过来的字符串格式ESP8266串口收到格式:

ssid:“xxx”,password:"xxxx"这个字符串设备MCU处理收到的这个字符串,将ssid和password提取出来。分别保存到缓存区SSID、PASSWORD。

4、设备让ESP8266进入STA模式设备MCU通过串口给ESP8266发送AT+CWMODE=1,让ESP8266进入STA模式。

5、设备连接路由器拿保存在缓存区的SSID和PASSWORD,设备通过串口给ESP8266发送连接指令AT+CWJAP=“SSID”,“PASSWORD”

6、连接公网服务器

===>120.78.136.134:8888AT+CIPSTART=“TCP”,“120.78.136.134”,9002

配网成功!如果以后不在初始化设置模式下,不会执行该流程,默认开机直接连接对应的热点和服务器。

二、ESP8266配网(使用上位机串口来给模组配置)

假设已经开发了一个上位机,这个上位机完成的功能如下:

1、上位机通过串口连接设备

2、具有设置wifi帐号和密码的功能(其实就是发送一条串口指令,带有wifi帐号和密码)

3、具有设置服务器ip和端口号的功能(其实就是发送一条串口指令,带有服务器ip和端口号)

配网流程

1、直接让设备进入STA模式 上位机通过串口给接有ESP8266的设备发送AT+CWMODE=1,让ESP8266进入STA模式。

2、设备接收到上位机发送过来的进入STA模式的指令,透传给ESP8266, 这时ESP8266如果设置成功,则处于STA模式。

3、特定模式下(初始化设置),线程等待上位机下发的指令指令格式:(1)设置wifi连接路由器SSID:“xxxx”,“PASSWORD”:“xxxxx”(2)设置wifi连接服务器SERVER_IP:“xxx.xxx.xxx.xxx”,PORT:“xxxx”

4、设备接收到上位机下发的指令,进行解析后分别保存在缓存区中。

5、设备连接路由器 拿保存在缓存区的SSID和PASSWORD,设备通过串口给ESP8266发送连接指令AT+CWJAP=“SSID”,“PASSWORD”

6、连接公网服务器

===>xxx.xx.xxx.xxx:xxxx例如:AT+CIPSTART=“TCP”,“120.78.136.134”,9002

配网成功!如果以后不在初始化设置模式下,不会执行该流程,默认开机直接连接对应的热点和服务器。

三、ESP8266配网(使用上位机网络TCP来给模组配置)

假设以及开发了一个上位机,这个上位机完成的功能如下:

1、上位机可以用TCP/IP连接wifi热点(ESP8266)===>需要知道esp8266的ip和端口号,通过window网络状态可以查到。

2、具有设置wifi帐号和密码的功能(其实就是发送一条串口指令,带有wifi帐号和密码)

3、具有设置服务器ip和端口号的功能(其实就是发送一条串口指令,带有服务器ip和端口号)

配网流程

设备端

1、直接让设备进入AP模式上位机通过串口给接有ESP8266的设备发送AT+CWMODE=2,让ESP8266进入AP模式。

指令:

AT+CWMODE=2

2、重启设备,确保AP模式设置成功指令:

AT+RST

3、开启多路连接指令:

AT+CIPMUX=1

4、为设备端创建热点指令:

AT+CWSAP=“WIFI名称”,“WIFI密码”,1,4

5、设备端启动服务器指令:

AT+CIPSERVER=1,8080

PC端

1、事先需要让PC去连接wifi热点===>WIFI名称、WIFI密码

2、通过网络连接详情查看当前热点的IPv4服务器地址

3、PC端开发的上位机连接IPv4服务器地址,端口号就是设备端指定的端口号:8080

4、PC端开发的上位机下发指令给设备端指令格式:

(1)设置wifi连接路由器SSID:“xxxx”,“PASSWORD”:“xxxxx”

(2)设置wifi连接服务器

SERVER_IP:“xxx.xxx.xxx.xxx”,PORT:“xxxx”

设备端

1、解析字符串,如果含有

SSID:“xxxx”,“PASSWORD”:“xxxxx”,取得ssid和password,保存到设备端的FLASH中,如果为其它,则设定接收出错的条件。

2、解析字符串,如果含有如下字符串:

SERVER_IP:“xxx.xxx.xxx.xxx”,PORT:“xxxx”

这时候程序解析取得server_ip和port,保存到设备端的FLASH中,如果为其它,则设定接收出错的条件。

3、如果已经解析完两个字符串,自动重启,切换到STA模式,取出ssid和password,连接ap,连接成功后,接下来取出flash中的server_ip和port,连接服务器,如果成功,则可进入数据上传,如果不成功,则返回ap连接,依次进行,直到成功后,此时程序中连接成功的标志会置一。

4、定时查询与服务器端确认是否连接成功,如果不成功,需要重新连接服务器。

5、可上传数据

ESP8266端,其实我已经写好了一个程序,只是还不是那么的完善,但现在已经可以用了,分享出来,大家可以去完善它。

大致程序框架设计如下,分别是配置WIFI的过程以及正常连接WIFI的过程:

//配置wifi网络
int Cofig_Wifi_NetWork(void)
{
    int ret = -1 ;
    char *buf = NULL;

    while(1)
    {
        switch(ESP8266_INFO.config_network_status)
        {
            case CHECK_WIFI_EXIST:
                ret = Wifi_Test_Exist();

                if(0 != ret)
                {
                    printf("wifi初始化失败,请检查硬件是否连接!\r\n");
                    ESP8266_INFO.config_network_status = CHECK_WIFI_EXIST ;
                    LED1(ON);
                    return -1 ;
                }
                else
                {
                    ESP8266_INFO.config_network_status = WIFI_SET_MODE ;
                    LED1(OFF);
                }
                break ;

            case WIFI_SET_MODE:
                ret = Wifi_Set_Mode(3);

                if(0 != ret)
                {
                    printf("wifi设置模式失败\r\n");
                    ESP8266_INFO.config_network_status = CHECK_WIFI_EXIST ;
                    LED1(ON);
                }
                else
                {
                    ESP8266_INFO.config_network_status = WIFI_BUILD_AP ;
                    LED1(OFF);
                }
                break ;

            case WIFI_BUILD_AP:
                printf("准备ap....\n");
                ret = ESP8266_BuildAP("ESP8266", "123456", WPA2_PSK);

                if(1 != ret)
                {
                    printf("wifi创建AP失败...\r\n");
                    ESP8266_INFO.config_network_status = CHECK_WIFI_EXIST ;
                    LED1(ON);
                }
                else
                {
                  ESP8266_INFO.config_network_status = WIFI_CONFIG_MULTI ;
                  LED1(OFF);
                  printf("创建ap成功\n");
                }
                break ;

            case WIFI_CONFIG_MULTI:
                printf("配置多连接模式!\r\n");
                ret = ESP8266_Enable_MultipleId(ENABLE);

                if(1 != ret)
                {
                    printf("配置多连接失败\n");
                    ESP8266_INFO.config_network_status = WIFI_BUILD_AP ;
                    LED1(ON);
                }
                else
                {
                  ESP8266_INFO.config_network_status = WIFI_START_SERVER ;
                  LED1(OFF);
                }
                break ;

            case WIFI_START_SERVER:
                ret = ESP8266_StartOrShutServer(ENABLE, "8080", "10") ;

                if(1 != ret)
                {
                    printf("创建端口号:%d失败\r\n", 8080);
                    ESP8266_INFO.config_network_status = WIFI_CONFIG_MULTI ;
                    LED1(ON);
                }
                else
                {
                  printf("创建端口号:%d成功\r\n", 8080);
                  ESP8266_INFO.config_network_status = WIFI_GET_AP_IP ;
                  LED1(OFF);
                }
                break ;

            case WIFI_GET_AP_IP:
                buf = malloc(20);
                if(buf == NULL)
                    return -1;

                if(1 != ESP8266_Inquire_ApIp(buf, 20))
                {
                    if(1 == ESP8266_StartOrShutServer(DISABLE, "8080", "5000"))
                    {
                        printf("关闭服务器成功!\r\n");
                        ESP8266_INFO.config_network_status = WIFI_START_SERVER ; //回到开启服务器的流程
                        LED1(OFF);
                    }
                    free(buf);
                }
                printf("获取ap ip:%s成功\r\n", buf);
                free(buf);
                ESP8266_INFO.config_network_status = WAIT_CLIENT_CONNECT;
                break ;

            case WAIT_CLIENT_CONNECT:
                while(1)
                {
                    //接收上位机连接
                    ret = ESP8266_Get_IdLinkStatus();
                    if(0 != ret)
                    {
                        printf("设备已和上位机建立连接....\r\n");
                        ESP8266_INFO.config_network_status = BACK_TO_CONFIG_PROCESS ;
                        LED1(ON);
                        break ;
                    }
                    LED2(ON);
                    Delay_ms (10);
                    LED2(OFF);
                    Delay_ms(10);
                }
                break ;

            default:
                break ;
        }

        if(ESP8266_INFO.config_network_status == BACK_TO_CONFIG_PROCESS)
        {
            LED1(OFF);
            LED2(OFF);
            LED3(OFF);
            break ;
        }
    }

    return 0 ;
}

//wifi正常连接流程
void Wifi_NetWork_Process(void)
{
    int ret = -1 ;

    while(1)
    {
        switch(ESP8266_INFO.wifi_status)
        {
            case WIFI_EXIST_CHECK:
                ret = Wifi_Test_Exist();

                if(0 != ret)
                {
                    printf("wifi硬件故障!\n");
                    return ;
                }

                ESP8266_INFO.wifi_status = WIFI_SET_MODE ;
                break ;

            case WIFI_SET_MODE:
                ret = Wifi_Set_Mode(STA);

                if(0 != ret)
                {
                    printf("wifi设置模式失败\r\n");
                    ESP8266_INFO.wifi_status = WIFI_EXIST_CHECK ;
                }
                else
                    ESP8266_INFO.wifi_status = WIFI_CONNECT_ROUTER;

                break ;

            case WIFI_CONNECT_ROUTER:
                ret = Wifi_Connect_Router((const char *)ESP8266_INFO.wifi_ssid, (const char *)ESP8266_INFO.wifi_password);

                if(ret != 0)
                {
                    printf("连接wifi热点失败\n");
                    ESP8266_INFO.wifi_status = WIFI_SET_MODE ;
                    return ;
                }
                else
                {
                    printf("连接wifi热点:%s成功\n", ESP8266_INFO.wifi_ssid);
                    ESP8266_INFO.wifi_status = WIFI_CLOSE_MULTI ;
                }

            case WIFI_CLOSE_MULTI:

                //关闭多连接
                if(1 != ESP8266_Enable_MultipleId(DISABLE))
                {
                    printf("关闭多连接失败!\n");
                    ESP8266_INFO.wifi_status = WIFI_CONNECT_ROUTER ;
                }
                else
                {
                    printf("关闭多连接成功!\n");
                    ESP8266_INFO.wifi_status = WIFI_CONNECT_SERVER ;
                }

                break ;

            case WIFI_CONNECT_SERVER:
                ret = Wifi_Connect_Server("TCP", (const char *)ESP8266_INFO.server_ip, atoi((char *)ESP8266_INFO.server_port));

                if(ret != 0)
                {
                    printf("连接服务器失败\n");
                    ESP8266_INFO.wifi_status = WIFI_CONNECT_ROUTER ;
                }
                else
                {
                    printf("连接服务器:%s成功\n", ESP8266_INFO.server_ip);
                    ESP8266_INFO.wifi_status = WIFI_CONFIG_OK ;
                }

                break ;

            default:
                break ;
        }

        //wifi连接成功
        if(WIFI_CONFIG_OK == ESP8266_INFO.wifi_status)
        {
            LED3(ON);
            break ;
        }
    }

    return ;
}


//返回当前子串在原字符串中的索引
int Sub_String_Index(char *str, char *sub_str)
{
    char *p1 = NULL ;
    char *__str = str ;
    char *__sub_str = sub_str ;
    p1 = strstr(__str, __sub_str);
    return  p1 - __str ;
}


/////////////////////////////////////ESP8266解析参数
int Esp8266_Process_Para(void)
{
    char *str = NULL ;
    char *p1 = NULL ;
    char *p2 = NULL ;
    int index1 = 0, index2 = 0 ;

    //开始wifi配置
    while(1)
    {
        //如果该标志为0,则代表上位机已经连上设备了
        if(BACK_TO_CONFIG_PROCESS == ESP8266_INFO.config_network_status)
        {
            if(0 == ESP8266_Get_IdLinkStatus())
            {
               printf("客户端已掉线,需重新连接....\n");
               LED2(ON);
               Delay_ms(300);
               LED2(OFF);
               Delay_ms(300);
            }
            //此时客户端没有掉线
            else
            {
              printf("客户端已连接,可下发数据....\n");
              //准备配置wifi_ssid
              str = ESP8266_ReceiveString(DISABLE);
              p1 = str + 12 ;

              if(NULL != strstr(p1, "SSID"))
              {
                  //拷贝wifi ssid
                  index1 = Sub_String_Index(p1, "=");
                  index2 = Sub_String_Index(p1, ";");
                  memcpy(ESP8266_INFO.wifi_ssid, p1 + index1 + 1, index2 - index1 - 1);
                  //拷贝wifi密码
                  p2 = p1 + index2 + 1 ;
                  index1 = Sub_String_Index(p2, "=") ;
                  index2 = Sub_String_Index(p2, ";") ;
                  memcpy(ESP8266_INFO.wifi_password, p2 + index1 + 1, index2 - index1 - 1);
                  printf("wifi_ssid:%s  wifi_password:%s\r\n", ESP8266_INFO.wifi_ssid, ESP8266_INFO.wifi_password);
                  macESP8266_Usart ("setting ssid_password success");            
                
                  
                  ESP8266_INFO.wifi_config_ap_flag = 1 ;
              }
              else if(NULL != strstr(p1, "SERVER_IP"))
              {
                  //拷贝服务器相关参数===>server_ip
                  index1 = Sub_String_Index(p1, "=");
                  index2 = Sub_String_Index(p1, ";");
                  memcpy(ESP8266_INFO.server_ip, p1 + index1 + 1, index2 - index1 - 1);
                  //拷贝服务器相关参数===>server_port
                  p2 = p1 + index2 + 1 ;
                  index1 = Sub_String_Index(p2, "=") ;
                  index2 = Sub_String_Index(p2, ";") ;
                  memcpy(ESP8266_INFO.server_port, p2 + index1 + 1, index2 - index1 - 1);
                  printf("server_ip:%s  server_port:%s\r\n", ESP8266_INFO.server_ip, ESP8266_INFO.server_port);
                  macESP8266_Usart ("setting server_ip port success");
                  ESP8266_INFO.wifi_cofnig_server_flag = 1 ;
              }

              //如果都配置了,则进入正常启动流程
              if((1 == ESP8266_INFO.wifi_config_ap_flag) && (1 == ESP8266_INFO.wifi_cofnig_server_flag))
              {
                  ESP8266_INFO.config_network_status = 1 ;
                  return ESP8266_INFO.config_network_status ;
              }
            }
        }
        else if(1 == ESP8266_INFO.config_network_status)
        {
            return ESP8266_INFO.config_network_status ;
        }
    }
}

手机APP设计得比较简陋

以下使用QT设计的一个简单的配置工具界面

本文分享自微信公众号 - 嵌入式开发圈(gh_d6ff851b4069)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-07-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • go语言调度器源代码情景分析之三:内存

    内存由大量内存单元组成,内存单元大小为1个字节(1字节包含8个二进制位), 每个内存单元都有一个编号,更专业的说法是每一个内存单元都有一个地址,我们在编写汇编代...

    阿波张
  • Linux 设备和驱动的相遇

    上一节的最后我们讲到设备树的三大作用,其最后一个作用也是最重要的作用:设备信息集合。这一节结合设备信息集合的详细讲解来认识一下设备和驱动是如何绑定的。所谓设备信...

    刘盼
  • 增长黑客死了!留存黑客又开始盛行!

    知乎盐选会员、京东Plus、阿里88VIP、美团外卖会员......忽如一夜春风来,互联网千家万户的梨花都开成了Costco。

    数据猿
  • 2-STM32+W5500+GPRS物联网开发基础篇-基础篇学习的内容

    https://www.cnblogs.com/yangfengwu/p/10936553.html

    杨奉武
  • go语言调度器源代码情景分析之二:CPU寄存器

    寄存器是CPU内部的存储单元,用于存放从内存读取而来的数据(包括指令)和CPU运算的中间结果,之所以要使用寄存器来临时存放数据而不是直接操作内存,一是因为CPU...

    阿波张
  • Spring Boot整合Elasticsearch

    Elasticsearch是一个全文搜索引擎,专门用于处理大型数据集。根据描述,自然而然使用它来存储和搜索应用程序日志。与Logstash和Kibana一起,它...

    JAVA葵花宝典
  • liteos 异常接管(十五)

    异常接管是操作系统对在运行期间发生异常的情况进行处理的一系列动作,譬如打印异常发生时当前函数调用栈信息、 cpu现场信息、任务的堆栈情况等。

    233333
  • JAVA、C、C++、Python同样是高级语言,为什么只有C和C++可以编写单片机程序?

    从事编程十几年,JAVA、C、C++、Python这四种编程语言都玩过,前三种玩的比较多,python做为兴趣爱好或者玩脚本的时候弄过,编程语言在使用的时候主要...

    程序员互动联盟
  • 3-ESP8266 SDK开发基础入门篇--点亮一个灯

    https://www.cnblogs.com/yangfengwu/p/11072834.html

    杨奉武
  • 基于MicroPython:TPYBoard心率监测器

    这几年智能穿戴设备大火,尤其是手环类,从Apple Watch到荣耀手环,再到不知名的某些品牌,智能穿戴设备是铺天盖地的来了。而其中心率监测基本上是所有穿戴设备...

    阿莉埃蒂

扫码关注云+社区

领取腾讯云代金券