WIFI模块(ESP8266)学习3


一、Arduino Core For ESP8266

fECKd1.png

二、ESP8266工作模式与ESP8266WIFI库

1、ESP8266工作模式

  1. Station模式(STA):

    ESP8266模块连接WIFI网络(通过接入点(Access Point))

    特点

    • 连接丢失,ESP8266会自动重连最近使用的接入点(会出问题,连不上);
    • 模块重启也会这样;
    • ESP8266将最后使用的接入点认证信息(ssid , psw)保存到Flash(非易失性)存储器中;
    • 若在Arduino IDE修改代码,但不更改WIFI工作模式或接入点认证信息,ESP8266使用保存在Flash上的数据重新连接。
  2. AP模式(soft-AP):

    (Access Point) ESP8266作为接入点建立WIFI网络,供Station模式下的模块连接

    特点

    • AP模式可用作STA模式的模块之间交换中转站(让模块处于同一WIFI网络下);
    • 可先在AP模式下发出WIFI信号,手机连接,高速该模块家里的WIFI认证信息,模块转为STA模式,连接目标WIFI。
  3. AP兼STA模式:

    以上两种模式的整合(应该是做软路由那个意思)

2、ESP8266WIFI库

概述:

fEDZ5Q.png

相关知识

  1. 名字里带Secure、SSL、TLS的,和安全校验有关(https);

  2. 带Client,和tcp客户端(发送端)有关;

  3. 带Server,和tcp服务端(接收端)有关;

  4. 带8266,针对ESP8266的代码封装;

  5. 带Scan,和WIFI扫描有关;

  6. 带STA,和ESP8266 Station模式有关;

  7. 带AP,和ESP8266 AP模式(AP热点)有关;

  8. ESP8266WiFiGeneric(8266模块通用库)包括:处理程序来管理WIFI事件,如连接、断开或获得ip,WIFI模式的变化,管理模块睡眠模式的功能,以ip地址解析hostName等;

  9. ESP8266WiFiGType.h文件,主要用来定义各种配置选项,如WIFI工作模式(WiFiMode),WiFi睡眠模式(WiFiSleep Type),wifi物理模式(WiFiPhyMode),wifi事件(WiFiEvent),wifi断开原因等;

  10. ESP8266WiFi库不仅仅局限于ESP8266WIFi.h和ESP8266WiFi.cpp这两个文件,但他们是最核心的统一入口;

  11. WiFiUdp库,在ESP8266WiFi功能基础上包装了UDP广播协议,适用于UDP通信,需另加头文件

    引入#include<ESP8266WiFi.h>一步到位

详解

①、WIFI通用功能库(ESP8266WiFiGeneric):

fErOte.png

②、STA库(ESP8266WiFiSTA):

  1. 配置连接:

    注意

    WiFi.mode(WIFI_STA);//最好人为加上STA设置(虽然默认是STA模式)
    WiFi.disconnect();//最好调用一下断连
    /*如果之前处于AP模式,再调begin()可能会进入STA+softAp模式
    *可检测当前模式(WiFi.getMode())
    */
    • 切换到STA模式(begin()

    源码:

    /**
    * 切换工作模式到STA模式,并自动连接到最近接入的wifi热点
    * @param void
    * @return void
    * @note 调用这个方法就会切换到STA模式,并且连接到最近使用的接入点(会从flash中读取之前存储的配置信息)
    * 		如果没有配置信息,那么这个方法基本上没有什么用。
    */
    wl_status_t begin()

    应用:

    WiFi.begin();
    • 切换到STA模式(begin(ssid,psw)

    应用:

    WiFi.begin(AP_SSID, AP_PSW);
    • 切换到STA模式(begin(ssid,psw,channel,bssid,connect)
    /**
    * 切换工作模式到STA模式,并根据connect属性来判断是否连接wifi
    * @param ssid       wifi热点名字
    * @param password   wifi热点密码
    * @param channel    wifi热点的通道号,用特定通信通信,可选参数
    * @param bssid      wifi热点的mac地址,可选参数
    * @param connect    boolean参数,默认等于true,当设置为false,不会去连接wifi热点,会建立module保存上面参数
    * @return wl_status_t  wifi状态
    * @note 调用这个方法就会切换到STA模式。
    *       如果connect等于true,会连接到ssid的wifi热点。
    *       如果connect等于false,不会连接到ssid的wifi热点,会建立module保存上面参数。
    */
    wl_status_t begin(char* ssid, char *passphrase = NULL, int32_t channel =0, const uint8_t* bssid = NULL, bool connect = true
    
    • 配置IP信息(config(local_ip,gateway,subnet,dns1,dns2)

    源码:

    /**
    * 禁止DHCP client,设置station 模式下的IP配置
    * @param  local_ip    station固定的ip地址(连接快)
    * @param  gateway     网关
    * @param  subnet      子网掩码(前3个参数都设置为0.0.0.0,则重启DHCP)
    * @param  dns1,dns2  可选参数定义域名服务器(dns)的ip地址,这些域名服务器
    *                     维护一个域名目录(如www.google.co.uk),并将它们翻译成ip地址  
    * @return boolean值,如果配置成功,返回true;
    *         如果配置没成功(模块没处于station或者station+soft AP模式),返回false;
    */
    bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000)
  2. 管理连接:

    • 重新连接网络(reconnect()

    源码:

    /**
    * 断开连接并且重新连接station到同一个AP
    * @param void
    * @return false or true
    *         返回false,意味着ESP8266不处于STA模式或者说Station在此之前没有连接到一个可接入点。
    *         返回true,意味着已经成功重新启动连接,但是用户仍应该去检测网络连接状态指导WL_CONNECTED。
    */
    bool reconnect()

    应用:

    WiFi.reconnect();
    while (WiFi.status() != WL_CONNECTED)
    {
      delay(500);
      Serial.print(".");
    }
    • 断开网络连接(disconnect()

    源码:

    /**
    * 断开wifi连接,设置当前配置SSID和pwd为null
    * @param wifioff 可选参数,设置为true,那么就会关闭Station模式
    * @return false or true 返回wl_status_t状态
    */
    bool disconnect(bool wifioff = false);
    • 是否连接网络(isConnected()

    源码:

    /**
    * 判断STA模式下是否连接上AP
    * @return 如果STA连接上AP,那么就返回true
    */
    bool isConnected();
    • 设置是否自动连接到最近接入点(setAutoConnect(bool autoReconnect)

    源码:

    /**
    * 当电源启动后,设置ESP8266在STA模式下是否自动连接flash中存储的AP
    * @param autoConnect bool 默认是自动连接
    * @return 返回保存状态 true or false
    */
    bool setAutoConnect(bool autoConnect);
    • 判断是否自动设置自动连接(getAutoConnect()

    源码:

    /**
    * 检测ESP8266 station模式下是否启动自动连接
    * @return 返回自动连接状态 true or false
    */
    bool getAutoConnect();
    • 设置是否自动重连到最近接入点(setAutoReconnect(bool autoReconnect)

    源码:

    /**
    * 设置当断开连接的时候是否自动重连
    *  网络断开后再设置无效
    * @param autoConnect bool
    * @return 返回保存状态 true or false
    */
    bool setAutoReconnect(bool autoReconnect);
    • 判断网络连接状态(waitForConnectResult()

    源码:

    /**
    * 等待直到ESP8266连接AP返回结果
    * @return uint8_t 连接结果
    *         1.WL_CONNECTED 成功连接
    *         2.WL_NO_SSID_AVAIL  匹配SSID失败(账号错误)
    *         3.WL_CONNECT_FAILED psw错误
    *         4.WL_IDLE_STATUS 当wi-fi正在不同的状态中变化
    *         5.WL_DISCONNECTED 这个模块没有配置STA模式
    */
    uint8_t waitForConnectResult();
  3. station信息:

    • 获取mac地址
      • macAddress(macAddr)
      • macAddress()

    源码:

    /**
     * 获取ESP station下的Mac地址
     * @param mac   uint8_t数组的指针,数组长度为Mac地址的长度,这里为6
     * @return      返回uint8_t数组的指针
     */
    uint8_t * macAddress(uint8_t* mac);
    /**
     * 获取ESP station下的Mac地址
     * @return  返回String的Mac地址
     */
    String macAddress();

    应用:

    //实例代码1 这只是部分代码 不能直接使用
    if (WiFi.status() == WL_CONNECTED)
    {
      uint8_t macAddr[6];
      WiFi.macAddress(macAddr);
      Serial.printf("Connected, mac address: %02x:%02x:%02x:%02x:%02x:%02x\n", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
      //Connected, mac address: 5C:CF:7F:08:11:17
    }
    
    //实例代码2 这只是部分代码 不能直接使用
    if (WiFi.status() == WL_CONNECTED)
    {
      Serial.printf("Connected, mac address: %s\n", WiFi.macAddress().c_str());
      Connected, mac address: 5C:CF:7F:08:11:17
    }
    • 获取ip地址(localIP()

    源码:

    /**
     * 返回ESP8266 STA模式下的IP地址
     * @return IP地址
     */
    IPAddress localIP();

    应用:

    if (WiFi.status() == WL_CONNECTED)
    {
      Serial.print("Connected, IP address: ");
      Serial.println(WiFi.localIP());
      //Connected, IP address: 192.168.1.10
    }
    • 获取子网掩码(subnetMask()

    源码:

    /**
     * 获取子网掩码的地址
     * @return 返回子网掩码的IP地址
     */
    IPAddress subnetMask();

    应用:

    Serial.print("Subnet mask: ");
    Serial.println(WiFi.subnetMask());
    //Subnet mask: 255.255.255.0
    • 获取网关地址(getwayIP()

    源码:

    /**
     * 获取网关IP地址
     * @return 返回网关IP地址
     */
    IPAddress gatewayIP();

    应用:

    //实例代码 这只是部分代码 不能直接使用
    Serial.printf("Gataway IP: %s\n", WiFi.gatewayIP().toString().c_str());
    //Gataway IP: 192.168.1.9
    • 获取dns地址(dnsIP()

    源码:

    /**
     * 获取DNS ip地址
     * @param dns_no dns序列号
     * @return 返回DNS服务的IP地址
     */
    IPAddress dnsIP(uint8_t dns_no = 0);

    应用:

    Serial.print("DNS #1, #2 IP: ");
    WiFi.dnsIP().printTo(Serial);
    Serial.print(", ");
    WiFi.dnsIP(1).printTo(Serial);
    Serial.println();
    //DNS #1, #2 IP: 62.179.1.60, 62.179.1.61
    • 获取host名字(hostname()

    源码:

    /**
     * 获取ESP8266 station DHCP的主机名
     * @return 主机名
     */
    String hostname();
    • 设置host名字(hostname(hostname))(3种)

    源码:

    /**
     * 设置ESP8266 station DHCP的主机名
     * @param aHostname 最大长度:32
     * @return ok
     */
    bool hostname(char* aHostname);
    bool hostname(const char* aHostname);
    bool hostname(String aHostname);

    应用:

    Serial.printf("Default hostname: %s\n", WiFi.hostname().c_str());
    WiFi.hostname("Station_Tester_02");
    Serial.printf("New hostname: %s\n", WiFi.hostname().c_str());
    //Default hostname: ESP_081117
    //New hostname: Station_Tester_02
    • 获取当前wifi连接状态(status()

    源码:

    /**
     * 返回wifi的连接状态
     * @return 返回wl_status_t中定义的其中一值,wl_status_t在 wl_definitions.h中定义
     */
    wl_status_t status();
    • 获取wifi网络名字(SSID()

    源码:

    /**
     * 返回当前通信网络的SSID
     * @return SSID
     */
    String SSID() const;

    应用:

    //实例代码 这只是部分代码 不能直接使用
    Serial.printf("SSID: %s\n", WiFi.SSID().c_str());
    //SSID: sensor-net
    • 获取wifi网络密码(psk()

    源码:

    /**
     * 返回当前通信网络的密码
     * @return psk
     */
    String psk() const;
    • 获取wifi网络macaddress(BSSID()

    源码:

    /**
     * 返回当前通信网络的mac地址
     * @return bssid uint8_t *
     */
    uint8_t * BSSID();
    String BSSIDstr();

    应用:

    Serial.printf("BSSID: %s\n", WiFi.BSSIDstr().c_str());
    //BSSID: 00:1A:70E:C1:68
    • 获取wifi网络的信号强度(RSSI()

    源码:

    /**
     * Return the current network RSSI.返回当前通信网络的信号强度,单位是dBm
     * @return  RSSI value
     */
    int32_t RSSI();

    应用:

    Serial.printf("RSSI: %d dBm\n", WiFi.RSSI());
    //RSSI: -68 dBm
  4. 智能配置:

    • 进入智能配置功能(beginSmartConfig()
    • 查询智能配置状态(smartConfigDone()
    • 停止智能配置功能(stopSmartConfig()
    • WiFi.beginWPSConfig()
    bool beginWPSConfig(void);
    /**
     * 启动 SmartConfig
     */
    bool beginSmartConfig();
    /**
     * 停止 SmartConfig
     */
    bool stopSmartConfig();
    /**
     * 查找SmartConfig状态来决定是否停止配置
     * @return smartConfig Done
     */
    bool smartConfigDone();

③、AP库(ESP8266WIFIAP)

  1. 配置soft-AP:
    • 启动开放式wifi网络(softAP(ssid)
    • 启动校验式wifi网络(softAP(ssid,password,channel,hidden)
    • 配置ap网络信息(softAPConfig(local_ip,gateway,subnet)
  2. 管理网络:
    • 获取连接到AP上的station的数目(softAPgetStationNum()
    • 关闭AP模式(softAPdisconnect(bool wifi off)
  3. 网络信息:
    • 获取ap的IP地址(softAPIP()
    • 获取ap的mac地址(softAPmacAddress()

④、WiFi扫描库(ESP8266WiFiScan):

一般使用异步扫描(不影响代码运行)

  1. 扫描操作:
    • 同步扫描周边有效wifi网络(scanNetworks()源码:
      /**
       * Start scan WiFi networks available
       * @param async         run in async mode(是否启动异步扫描)
       * @param show_hidden   show hidden networks(是否扫描隐藏网络)
       * @param channel       scan only this channel (0 for all channels)(是否扫描特定通道)
       * @param ssid*         scan for only this ssid (NULL for all ssid's)(是否扫描特定的SSID)
       * @return Number of discovered networks
       */
      int8_t scanNetworks(bool async = false, bool show_hidden = false, uint8 channel = 0, uint8* ssid = NULL);
      应用:
      //实例代码 这只是部分代码 不能直接使用
      //同步扫描
      int n = WiFi.scanNetworks();//不需要填任何参数
      Serial.println("scan done");
      if (n == 0) {
          Serial.println("no networks found");
      } else {
          Serial.println(" networks found");
      }
    • 异步扫描周边有效wifi网络,包括隐藏网络(scanNetworks(bool async,bool show_hiden)应用:
      //实例代码 这只是部分代码 不能直接使用
      //异步扫描
      WiFi.scanNetworks(true);
      // print out Wi-Fi network scan result uppon completion
      int n = WiFi.scanComplete();
      if(n >= 0){
        Serial.printf("%d network(s) found\n", n);
        for (int i = 0; i < n; i++){
           Serial.printf("%d: %s, Ch:%d (%ddBm) %s\n", i+1, WiFi.SSID(i).c_str(), WiFi.channel(i), WiFi.RSSI(i), WiFi.encryptionType(i) == ENC_TYPE_NONE ? "open" : "");
        }
        //打印一次结果之后把缓存中的数据清掉
        WiFi.scanDelete();
      }
    • 检测异步扫描的结果(scanComplete()源码:
      /**
       * called to get the scan state in Async mode(异步扫描的结果函数)
       * @return scan result or status
       *          -1 if scan not find
       *          -2 if scan not triggered
       */
      int8_t scanComplete();
    • 从内存中删除最近扫描结果(scanDelete()) 如果不删除,则会叠加上次扫描结果;
      /**
       * delete last scan result from RAM(从内存中删除最近的扫描结果)
       */
      void scanDelete();
    • 异步扫描周边wifi网络,并回调结果(scanNetworkAsync(onComplete,show_hidden)源码:
      /**
       * Starts scanning WiFi networks available in async mode
       * @param onComplete    the event handler executed when the scan is done
       * @param show_hidden   show hidden networks
        */
      void scanNetworksAsync(std::function<void(int)> onComplete, bool show_hidden = false);
      应用:
      //实例代码
      #include "ESP8266WiFi.h"
      void prinScanResult(int networksFound)
      {
        Serial.printf("%d network(s) found\n", networksFound);
        for (int i = 0; i < networksFound; i++)
        {
          Serial.printf("%d: %s, Ch:%d (%ddBm) %s\n", i + 1, WiFi.SSID(i).c_str(), WiFi.channel(i), WiFi.RSSI(i), WiFi.encryptionType(i) == ENC_TYPE_NONE ? "open" : "");
        }
      }
      void setup()
      {
        Serial.begin(115200);
        Serial.println();
       
        WiFi.mode(WIFI_STA);
        WiFi.disconnect();
        delay(100);
       
        WiFi.scanNetworksAsync(prinScanResult);
      }
      void loop() {}
      //应该会打印如下类似的显示
      //5 network(s) found
      //1: Tech_D005107, Ch:6 (-72dBm)
      //2: HP-Print-A2-Photosmart 7520, Ch:6 (-79dBm)
      //3: ESP_0B09E3, Ch:9 (-89dBm) open
      //4: Hack-4-fun-net, Ch:9 (-91dBm)
      //5: UPC Wi-Free, Ch:11 (-79dBm)
  2. 扫描结果:
    • 获取wifi网络名字(SSID(int networkltem)
      /**
       * Return the SSID discovered during the network scan.
       * @param i     specify from which network item want to get the information
       * @return       ssid string of the specified item on the networks scanned list
       */
      String SSID(uint8_t networkItem);
    • 获取wifi网络信号强度(RSS(int networkltem)
      /**
       * Return the RSSI of the networks discovered during the scanNetworks(信号强度)
       * @param i specify from which network item want to get the information
       * @return  signed value of RSSI of the specified item on the networks scanned list
       */
      int32_t RSSI(uint8_t networkItem);
    • 获取wifi网络加密方式(encryption Type(int networkltem)
      /**
       * Return the encryption type of the networks discovered during the scanNetworks(加密方式)
       * @param i specify from which network item want to get the information
       * @return  encryption type (enum wl_enc_type) of the specified item on the networks scanned list
       * ............ Values map to 802.11 encryption suites.....................
       *    AUTH_OPEN          ---->     ENC_TYPE_WEP  = 5,
       *    AUTH_WEP           ---->     ENC_TYPE_TKIP = 2,
       *    AUTH_WPA_PSK       ---->     ENC_TYPE_CCMP = 4,
       * ........... except these two, 7 and 8 are reserved in 802.11-2007.......
       *    AUTH_WPA2_PSK      ---->     ENC_TYPE_NONE = 7,
       *    AUTH_WPA_WPA2_PSK  ---->     ENC_TYPE_AUTO = 8
       */
      uint8_t encryptionType(uint8_t networkItem);
    • 获取wifi网络mac地址(BSSID(int networkltem)
      /**
       * return MAC / BSSID of scanned wifi (物理地址)
       * @param i specify from which network item want to get the information
       * @return uint8_t * MAC / BSSID of scanned wifi
       */
      uint8_t * BSSID(uint8_t networkItem);
       
      /**
       * return MAC / BSSID of scanned wifi (物理地址)
       * @param i specify from which network item want to get the information
       * @return uint8_t * MAC / BSSID of scanned wifi
       */
      String BSSIDstr(uint8_t networkItem);
    • 获取整体网络信息,名字,信号强度等(getNetworkInfo) 入参前面多数加了&,意味着调完函数后外面获取到的详细洗信息;
      /**
       * loads all infos from a scanned wifi in to the ptr parameters
       * @param networkItem uint8_t
       * @param ssid  const char**
       * @param encryptionType uint8_t *
       * @param RSSI int32_t *
       * @param BSSID uint8_t **
       * @param channel int32_t *
       * @param isHidden bool *
       * @return (true if ok)
       */        
      bool getNetworkInfo(uint8_t networkItem, String &ssid, uint8_t &encryptionType, int32_t &RSSI, uint8_t* &BSSID, int32_t &channel, bool &isHidden);
    • 获取wifi网络通道号
      /**
       * return channel of scanned wifi(通道号)
       */
      int32_t channel(uint8_t networkItem);
    • 判断wifi网络是否是隐藏网络
      /**
       * return if the scanned wifi is Hidden (no SSID)(判断扫描到的wifi是否是隐藏wifi)
       * @param networkItem specify from which network item want to get the information
       * @return bool (true == hidden)
       */
      bool isHidden(uint8_t networkItem);

⑤、TCP客户端(WiFiClient):

TCP与HTTP关系:

TCP是底层通讯协议,定义的是数据传输和连接方式的规范;

HTTP是应用层协议,定义的是传输数据的内容规范;

HTTP协议中的数据是利用TCP协议传输的,所以支持HTTP就支持TCP。

  1. 连接操作:
    • 启动tcp连接(connect(host,port)
    • 判断client是否还在连接(connected()
    • 停止tcp连接(stop()
  2. 发送http请求操作:
    • print()
    • println()
    • write()
  3. 响应操作:
    • 判断是否有响应数据(available()
    • 查找响应数据某个字符串(find()
    • 读取响应数据直到某个字符串,会清除掉(readStringUntil
    • 读取响应数据中的一个字符,不清除(peek()
    • 读取固定大小的响应数据,不清除(peekBytes(buf,size)
    • 读取响应数据中的一个字符,清掉(read()
    • 读取固定大小的响应数据,清掉(read(buf,size)
    • 清掉缓冲区(flush()
  4. 普通设置:setNoDelay()

⑥、TCP客户端(WiFiClientSecure https):

⑦、TCP服务端(WiFiServer):

  1. 管理server:
    1. 设置tcp server:
      • 新增tcp server(WiFiServer server(port)
      • 启动tcp server(begin()
      • 关闭小包合并发送功能(setNoDelay(true)
    2. 停止server:
      • close()
      • stop()(内部实现直接调用close())
    3. server状态 : server.status()
  2. 等待WiFiClient访问:
    • 判断是否有新的client连接进来(available()
    • 判断是否有client连接(has Client()
  3. 读取WiFiClient的请求:参考WiFiClient里面的响应方法

⑧、TCP服务端(WiFiServerSecure https)

⑨、ESP8266WiFi库自带方法:

  • 调用调试信息(printDiag(serial)

总结:(感谢博哥的图)fedfFe.png

三、示例:

1、AP模式:

/**
 *    AP模式下,演示AP 函数方法的使用(最多连接4个)
 */
#include <ESP8266WiFi.h>
 
#define AP_SSID "AP_Test" //这里改成你的AP名字
#define AP_PSW  "12345678" //这里改成你的AP密码 8位以上
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)
 
IPAddress local_IP(192,168,4,1);
IPAddress gateway(192,168,4,1);
IPAddress subnet(255,255,255,0);
 
void setup(){
  //设置串口波特率,以便打印信息
  DebugBegin(115200);
  //延时2s 为了演示效果
  delay(2000);
  DebugPrint("Setting soft-AP configuration ... ");
  //配置AP信息
  WiFi.mode(WIFI_AP);
  DebugPrintln(WiFi.softAPConfig(local_IP, gateway, subnet) ? "Ready" : "Failed!");
  //启动AP模式,并设置账号和密码
  DebugPrint("Setting soft-AP ... ");
  boolean result = WiFi.softAP(AP_SSID, AP_PSW);
  if(result){
    DebugPrintln("Ready");
    //输出 soft-ap ip地址
    DebugPrintln(String("Soft-AP IP address = ") + WiFi.softAPIP().toString());
    //输出 soft-ap mac地址
    DebugPrintln(String("MAC address = ") + WiFi.softAPmacAddress().c_str());
  }else{
    DebugPrintln("Failed!");
  }
  DebugPrintln("Setup End");
}
 
void loop() {
  //不断打印当前的station个数
  DebugPrintln(String("Stations connected =") + WiFi.softAPgetStationNum());
  delay(3000);
}

2、STA模式

/**
 * Demo1:
 *    statin模式下,创建一个连接到可接入点(wifi热点),并且打印IP地址
 */
#include <ESP8266WiFi.h>
 
#define AP_SSID "XU-ChinaNet" //这里改成你的wifi名字
#define AP_PSW  "15358228063"//这里改成你的wifi密码
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)
 
void setup(){
  //设置串口波特率,以便打印信息
  DebugBegin(115200);
  //延时2s 为了演示效果
  delay(2000);
  DebugPrintln("Setup start");
  //启动STA模式,并连接到wifi网络
  WiFi.mode(WIFI_STA);//最好人为加上STA设置(虽然默认是STA模式)
  WiFi.disconnect();//最好调用一下断连
  WiFi.begin(AP_SSID, AP_PSW);
  DebugPrint(String("Connecting to ")+AP_SSID);
  //判断网络状态是否连接上,没连接上就延时500ms,并且打出一个点,模拟连接过程
  //笔者扩展:加入网络一直都连不上 是否可以做个判断,由你们自己实现
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    DebugPrint(".");
  }
  DebugPrintln("");
  DebugPrint("Connected, IP address: ");
  //输出station IP地址,这里的IP地址由DHCP分配
  DebugPrintln(WiFi.localIP());
  DebugPrintln("Setup End");
}
void loop() {
}
/**
 * Demo2:固定IP
 *    statin模式下,配置IP地址,网关地址,子网掩码,并且打印IP地址
 */
#include <ESP8266WiFi.h>
 
#define AP_SSID "XU-ChinaNet" //这里改成你的wifi名字
#define AP_PSW  "15358228063"//这里改成你的wifi密码
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)
 
IPAddress staticIP(192,168,1,22);//固定IP地址
IPAddress gateway(192,168,1,9);//网关地址
IPAddress subnet(255,255,255,0);//子网掩码地址
 
void setup(){
  //设置串口波特率,以便打印信息
  DebugBegin(115200);
  //延时2s 为了演示效果
  delay(2000);
  DebugPrintln("Setup start");
  //启动STA模式,并连接到wifi网络
  WiFi.begin(AP_SSID, AP_PSW);
  DebugPrint(String("Connecting to ")+AP_SSID);
  //配置网络
  WiFi.config(staticIP,gateway,subnet);
  //判断网络状态是否连接上,没连接上就延时500ms,并且打出一个点,模拟连接过程
  //笔者扩展:加入网络一直都连不上 是否可以做个判断,由你们自己实现
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    DebugPrint(".");
  }
  DebugPrintln("");
 
  DebugPrint("Connected, IP address: ");
  //输出station IP地址,这里的IP地址理论上就是上面配置的
  DebugPrintln(WiFi.localIP());
  DebugPrintln("Setup End");
}
 
void loop() {
}
/**
 * Demo3:
 *    statin模式下,创建一个连接到可接入点(wifi热点),并且打印station信息
 */
#include <ESP8266WiFi.h>
 
#define AP_SSID "XU-ChinaNet" //这里改成你的wifi名字
#define AP_PSW  "15358228063"//这里改成你的wifi密码
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)
 
void setup(){
  //设置串口波特率,以便打印信息
  DebugBegin(115200);
  //延时2s 为了演示效果
  delay(2000);
  DebugPrintln("Setup start");
  //启动STA模式,并连接到wifi网络
  WiFi.begin(AP_SSID, AP_PSW);
  //设置自动连接
  WiFi.setAutoConnect(true);
  //设置自动重连
  WiFi.setAutoReconnect(true);
  DebugPrint(String("Connecting to ")+AP_SSID);
  //判断网络状态是否连接上,没连接上就延时500ms,并且打出一个点,模拟连接过程
  //笔者扩展:加入网络一直都连不上 是否可以做个判断,由你们自己实现
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    DebugPrint(".");
  }
  DebugPrintln("");
 
  DebugPrintln("rint Network Info:");
  if (WiFi.status() == WL_CONNECTED){
     //输出mac地址
     DebugPrintln(String("Connected, mac address: ")+WiFi.macAddress().c_str());
     
     //输出station IP地址,这里的IP地址由DHCP分配
     DebugPrintln(String("Connected, IP address: ")+WiFi.localIP().toString());
     
     //输出子网掩码地址
     DebugPrintln(String("Subnet mask: ")+WiFi.subnetMask().toString());
     
     //输出网关 IP地址
     DebugPrintln(String("Gataway IP: ")+WiFi.gatewayIP().toString());
     
     //输出hostname
     DebugPrintln(String("Default hostname: ")+WiFi.hostname());
     //设置新的hostname
     WiFi.hostname("Station_host_123");
     DebugPrintln(String("New hostname: ")+WiFi.hostname());
     
     //输出SSID
     DebugPrintln(String("SSID: ")+WiFi.SSID());
 
     //输出psk
     DebugPrintln(String("psk: ")+WiFi.psk());
     
     //输出BSSID
     DebugPrintln(String("BSSID: ")+WiFi.BSSIDstr());
     
     //输出RSSI
     DebugPrintln(String("RSSI: ") + WiFi.RSSI() + " dBm");
  }
  
  DebugPrintln("Setup End");
}
 
void loop() {
}

3、扫描:

/**
 * Demo:
 *    STA模式下,演示同步扫描Scan wifi功能
 */
#include <ESP8266WiFi.h>
 
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)
 
void setup() {
  //设置串口波特率,以便打印信息
  DebugBegin(115200);
  //延时5s 为了演示效果
  delay(5000);
  // 我不想别人连接我,只想做个站点
  WiFi.mode(WIFI_STA);
  //断开连接
  WiFi.disconnect();
  delay(100);
  DebugPrintln("Setup done");
}
 
void loop() {
  DebugPrintln("scan start");
  // 同步扫描,等待返回结果
  int n = WiFi.scanNetworks();
  DebugPrintln("scan done");
  if (n == 0){
    DebugPrintln("no networks found");
  }else{
    DebugPrint(n);
    DebugPrintln(" networks found");
    for (int i = 0; i < n; ++i){
      DebugPrint(i + 1);
      DebugPrint(": ");
      //打印wifi账号
      DebugPrint(WiFi.SSID(i));
      DebugPrint(",");
      DebugPrint(String("Ch:")+WiFi.channel(i));
      DebugPrint(",");
      DebugPrint(WiFi.isHidden(i)?"hide":"show");
      DebugPrint(" (");
      //打印wifi信号强度
      DebugPrint(WiFi.RSSI(i));
      DebugPrint("dBm");
      DebugPrint(")");
      //打印wifi加密方式
      DebugPrintln((WiFi.encryptionType(i) == ENC_TYPE_NONE)?"open":"*");
      delay(10);
    }
  }
  DebugPrintln("");
  // 延时5s之后再次扫描
  delay(5000);
}
/**
 * Demo:
 *    STA模式下,演示异步扫描Scan wifi功能
 */
#include <ESP8266WiFi.h>
 
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)
//定义一个扫描时间间隔
#define SCAN_PERIOD 5000
long lastScanMillis;
 
void setup() {
  //设置串口波特率,以便打印信息
  DebugBegin(115200);
  //延时5s 为了演示效果
  delay(5000);
  // 我不想别人连接我,只想做个站点
  WiFi.mode(WIFI_STA);
  //断开连接
  WiFi.disconnect();
  delay(100);
  DebugPrintln("Setup done");
}
 
void loop() {
 
 long currentMillis = millis();
 //触发扫描
 if (currentMillis - lastScanMillis > SCAN_PERIOD){
    WiFi.scanNetworks(true);
    Serial.print("\nScan start ... ");
    lastScanMillis = currentMillis;
  }
 
  // 判断是否有扫描结果
  int n = WiFi.scanComplete();
  if(n >= 0){
    Serial.printf("%d network(s) found\n", n);
    for (int i = 0; i < n; i++){
      Serial.printf("%d: %s, Ch:%d (%ddBm) %s\n", i+1, WiFi.SSID(i).c_str(), WiFi.channel(i), WiFi.RSSI(i), WiFi.encryptionType(i) == ENC_TYPE_NONE ? "open" : "");
    }
    //打印完一次扫描结果之后  删除内存保存结果
    WiFi.scanDelete();
  }
}
/**
 * Demo:
 *    STA模式下,演示异步扫描Scan wifi功能
 */
#include <ESP8266WiFi.h>
 
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)
 
/**
 * 打印扫描结果
 * @param networksFound 结果个数
 */
void prinScanResult(int networksFound){
  Serial.printf("%d network(s) found\n", networksFound);
  for (int i = 0; i < networksFound; i++)
  {
    Serial.printf("%d: %s, Ch:%d (%ddBm) %s\n", i + 1, WiFi.SSID(i).c_str(), WiFi.channel(i), WiFi.RSSI(i), WiFi.encryptionType(i) == ENC_TYPE_NONE ? "open" : "");
  }
}
 
void setup() {
  //设置串口波特率,以便打印信息
  DebugBegin(115200);
  //延时5s 为了演示效果
  delay(5000);
  // 我不想别人连接我,只想做个站点
  WiFi.mode(WIFI_STA);
  //断开连接
  WiFi.disconnect();
  delay(100);
  DebugPrintln("Setup done");
  Serial.print("\nScan start ... ");
  WiFi.scanNetworksAsync(prinScanResult);
}
 
void loop() {
}

4、通用库处理事件:

  1. 官方示例:(AP模式)
/*
    This sketch shows how to use WiFi event handlers.

    In this example, ESP8266 works in AP mode.
    Three event handlers are demonstrated:
    - station connects to the ESP8266 AP
    - station disconnects from the ESP8266 AP
    - ESP8266 AP receives a probe request from a station
*/

#include <ESP8266WiFi.h>
#include <stdio.h>

const char* ssid     = "ap-ssid";
const char* password = "ap-password";

WiFiEventHandler stationConnectedHandler;
WiFiEventHandler stationDisconnectedHandler;
WiFiEventHandler probeRequestPrintHandler;
WiFiEventHandler probeRequestBlinkHandler;

bool blinkFlag;

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  // 不保存任何wifi配置到flash
  WiFi.persistent(false);

  // 建立一个AP
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password);

  // 注册事件处理器
  // 回调函数会在事件发生时被调用
  // onStationConnected函数会在每一次有station连接时调用
  stationConnectedHandler = WiFi.onSoftAPModeStationConnected(&onStationConnected);
  // onStationDisconnected函数会在每一次有station断开时调用
  stationDisconnectedHandler = WiFi.onSoftAPModeStationDisconnected(&onStationDisconnected);
  // onProbeRequestPrint和onProbeRequestBlink函数会在每一次收到探针请求时调用
  // onProbeRequestPrint会打印station的mac地址和信号强度到串口监视器
  // onProbeRequestBlink会闪烁LED
  probeRequestPrintHandler = WiFi.onSoftAPModeProbeRequestReceived(&onProbeRequestPrint);
  probeRequestBlinkHandler = WiFi.onSoftAPModeProbeRequestReceived(&onProbeRequestBlink);
}

void onStationConnected(const WiFiEventSoftAPModeStationConnected& evt) {
  Serial.print("Station connected: ");
  Serial.println(macToString(evt.mac));
}

void onStationDisconnected(const WiFiEventSoftAPModeStationDisconnected& evt) {
  Serial.print("Station disconnected: ");
  Serial.println(macToString(evt.mac));
}

void onProbeRequestPrint(const WiFiEventSoftAPModeProbeRequestReceived& evt) {
  Serial.print("Probe request from: ");
  Serial.print(macToString(evt.mac));
  Serial.print(" RSSI: ");
  Serial.println(evt.rssi);
}

void onProbeRequestBlink(const WiFiEventSoftAPModeProbeRequestReceived&) {
  // 我们不能在事件处理函数中调用延时函数或者其他阻塞函数
  // 因此这里设置一个标志位
  blinkFlag = true;
}

void loop() {
  if (millis() > 10000 && probeRequestPrintHandler) {
    // 10s之后,禁止 onProbeRequestPrint
    Serial.println("Not printing probe requests any more (LED should still blink)");
    probeRequestPrintHandler = WiFiEventHandler();
  }
  if (blinkFlag) {
    blinkFlag = false;
    digitalWrite(LED_BUILTIN, LOW);
    delay(100);
    digitalWrite(LED_BUILTIN, HIGH);
  }
  delay(10);
}

String macToString(const unsigned char* mac) {
  char buf[20];
  snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  return String(buf);
}
  1. station模式:
#include <ESP8266WiFi.h>

const char *ssid = "********";
const char *password = "********";

WiFiEventHandler STAConnected;
WiFiEventHandler STADisconnected;
WiFiEventHandler STAGotIP;

void ConnectedHandler(const WiFiEventStationModeConnected &event)
{
    Serial.println(WiFi.status());
    Serial.println("模块连接到网络");
}

void DisconnectedHandler(const WiFiEventStationModeDisconnected &event)
{
    Serial.println(WiFi.status());
    Serial.println("模块从网络断开");
}

void setup()
{
    Serial.begin(115200);
    Serial.println();

    STAConnected = WiFi.onStationModeConnected(ConnectedHandler);
    STADisconnected = WiFi.onStationModeDisconnected(DisconnectedHandler);
    STAGotIP = WiFi.onStationModeGotIP([](const WiFiEventStationModeGotIP &event) {
        Serial.println(WiFi.status());
        Serial.println("模块获得IP");
    });

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    Serial.println(WiFi.status());
}

void loop()
{
    delay(5000); //等待5秒
    WiFi.disconnect(); //断开当前网络连接
}

5、TCP客户端(client)

  1. 演视WiFiClient与TCP server之间通信功能(使用TCP调试助手(TCP/UDP Socket调试工具))在TCP调试助手上建立一个TCP server, IP地址是192.168.1.102,端口号是8234。
/**
 * Demo:
 *    STA模式下,演示WiFiClient与TCP server之间的通信功能
 *    本实验需要跟TCP调试助手一起使用。
 */
#include <ESP8266WiFi.h>
 
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)
 
#define AP_SSID "XU-ChinaNet" //这里改成你的wifi名字
#define AP_PSW  "15358228063"//这里改成你的wifi密码
 
const uint16_t port = 8234;
const char * host = "192.168.1.8"; // ip or dns
WiFiClient client;//创建一个tcp client连接
 
void setup() {
  //设置串口波特率,以便打印信息
  DebugBegin(115200);
  //延时5s 为了演示效果
  delay(5000);
  // 我不想别人连接我,只想做个站点
  WiFi.mode(WIFI_STA);
  WiFi.begin(AP_SSID,AP_PSW);
 
  DebugPrint("Wait for WiFi... ");
  //等待wifi连接成功
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
 
  DebugPrintln("");
  DebugPrintln("WiFi connected");
  DebugPrint("IP address: ");
  DebugPrintln(WiFi.localIP());
 
  delay(500);
}
 
void loop() {
  
  DebugPrint("connecting to ");
  DebugPrintln(host);
 
  if (!client.connect(host, port)) {
    DebugPrintln("connection failed");
    DebugPrintln("wait 5 sec...");
    delay(5000);
    return;
  }
 
  // 发送数据到Tcp server
  DebugPrintln("Send this data to server");
  client.println(String("Send this data to server"));
 
  //读取从server返回到响应数据
  String line = client.readStringUntil('\r');
  DebugPrintln(line);
 
  DebugPrintln("closing connection");
  client.stop();
 
  DebugPrintln("wait 5 sec...");
  delay(5000);
}
  1. 通过TCP client包装Http请求协议去调用天气接口获取天气信息

    (使用ArduinoJson库,尽量使用5.X版本)

/**
 * Demo:
 *    演示Http请求天气接口信息
 */
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
 
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)
 
const char* ssid     = "TP-LINK_5344";         // XXXXXX -- 使用时请修改为当前你的 wifi ssid
const char* password = "6206908you11011010";         // XXXXXX -- 使用时请修改为当前你的 wifi 密码
const char* host = "api.seniverse.com";
const char* APIKEY = "wcmquevztdy1jpca";        //API KEY
const char* city = "guangzhou";
const char* language = "zh-Hans";//zh-Hans 简体中文  会显示乱码
  
const unsigned long BAUD_RATE = 115200;                   // serial connection speed
const unsigned long HTTP_TIMEOUT = 5000;               // max respone time from server
const size_t MAX_CONTENT_SIZE = 1000;                   // max size of the HTTP response
 
// 我们要从此网页中提取的数据的类型
struct WeatherData {
  char city[16];//城市名称
  char weather[32];//天气介绍(多云...)
  char temp[16];//温度
  char udate[32];//更新时间
};
  
WiFiClient client;
char response[MAX_CONTENT_SIZE];
char endOfHeaders[] = "\r\n\r\n";
 
void setup() {
  // put your setup code here, to run once:
  WiFi.mode(WIFI_STA);     //设置esp8266 工作模式
  DebugBegin(BAUD_RATE);
  DebugPrint("Connecting to ");//写几句提示,哈哈
  DebugPrintln(ssid);
  WiFi.begin(ssid, password);   //连接wifi
  WiFi.setAutoConnect(true);
  while (WiFi.status() != WL_CONNECTED) {
    //这个函数是wifi连接状态,返回wifi链接状态
    delay(500);
    DebugPrint(".");
  }
  DebugPrintln("");
  DebugPrintln("WiFi connected");
  delay(500);
  DebugPrintln("IP address: ");
  DebugPrintln(WiFi.localIP());//WiFi.localIP()返回8266获得的ip地址
  client.setTimeout(HTTP_TIMEOUT);
}
 
void loop() {
  // put your main code here, to run repeatedly:
  //判断tcp client是否处于连接状态,不是就建立连接
  while (!client.connected()){
     if (!client.connect(host, 80)){
         DebugPrintln("connection....");
         delay(500);
     }
  }
  //发送http请求 并且跳过响应头 直接获取响应body
  if (sendRequest(host, city, APIKEY) && skipResponseHeaders()) {
    //清除缓冲
    clrEsp8266ResponseBuffer();
    //读取响应数据
    readReponseContent(response, sizeof(response));
    WeatherData weatherData;
    if (parseUserData(response, &weatherData)) {
      printUserData(&weatherData);
    }
  }
  delay(5000);//每5s调用一次
}
 
/**
* @发送http请求指令
*/
bool sendRequest(const char* host, const char* cityid, const char* apiKey) {
  // We now create a URI for the request
  //心知天气  发送http请求
  String GetUrl = "/v3/weather/now.json?key=";
  GetUrl += apiKey;
  GetUrl += "&location=";
  GetUrl += city;
  GetUrl += "&language=";
  GetUrl += language;
  // This will send the request to the server
  client.print(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  DebugPrintln("create a request:");
  DebugPrintln(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n");
  delay(1000);
  return true;
}
  
/**
* @Desc 跳过 HTTP 头,使我们在响应正文的开头
*/
bool skipResponseHeaders() {
  // HTTP headers end with an empty line
  bool ok = client.find(endOfHeaders);
  if (!ok) {
    DebugPrintln("No response or invalid response!");
  }
  return ok;
}
  
/**
* @Desc 从HTTP服务器响应中读取正文
*/
void readReponseContent(char* content, size_t maxSize) {
  size_t length = client.readBytes(content, maxSize);
  delay(100);
  DebugPrintln("Get the data from Internet!");
  content[length] = 0;
  DebugPrintln(content);
  DebugPrintln("Read data Over!");
  client.flush();//清除一下缓冲
}
  
/**
 * @Desc 解析数据 Json解析
 * 数据格式如下:
 * {
 *    "results": [
 *        {
 *            "location": {
 *                "id": "WX4FBXXFKE4F",
 *                "name": "北京",
 *                "country": "CN",
 *                "path": "北京,北京,中国",
 *                "timezone": "Asia/Shanghai",
 *                "timezone_offset": "+08:00"
 *            },
 *            "now": {
 *                "text": "多云",
 *                "code": "4",
 *                "temperature": "23"
 *            },
 *            "last_update": "2017-09-13T09:51:00+08:00"
 *        }
 *    ]
 *}
 */
bool parseUserData(char* content, struct WeatherData* weatherData) {
//    -- 根据我们需要解析的数据来计算JSON缓冲区最佳大小
//   如果你使用StaticJsonBuffer时才需要
//    const size_t BUFFER_SIZE = 1024;
//   在堆栈上分配一个临时内存池
//    StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
//    -- 如果堆栈的内存池太大,使用 DynamicJsonBuffer jsonBuffer 代替
  DynamicJsonBuffer jsonBuffer;
   
  JsonObject& root = jsonBuffer.parseObject(content);
   
  if (!root.success()) {
    DebugPrintln("JSON parsing failed!");
    return false;
  }
    
  //复制我们感兴趣的字符串
  strcpy(weatherData->city, root["results"][0]["location"]["name"]);
  strcpy(weatherData->weather, root["results"][0]["now"]["text"]);
  strcpy(weatherData->temp, root["results"][0]["now"]["temperature"]);
  strcpy(weatherData->udate, root["results"][0]["last_update"]);
  //  -- 这不是强制复制,你可以使用指针,因为他们是指向“内容”缓冲区内,所以你需要确保
  //   当你读取字符串时它仍在内存中
  return true;
}
   
// 打印从JSON中提取的数据
void printUserData(const struct WeatherData* weatherData) {
  DebugPrintln("Print parsed data :");
  DebugPrint("City : ");
  DebugPrint(weatherData->city);
  DebugPrint(", \t");
  DebugPrint("Weather : ");
  DebugPrint(weatherData->weather);
  DebugPrint(",\t");
  DebugPrint("Temp : ");
  DebugPrint(weatherData->temp);
  DebugPrint(" C");
  DebugPrint(",\t");
  DebugPrint("Last Updata : ");
  DebugPrint(weatherData->udate);
  DebugPrintln("\r\n");
}
   
// 关闭与HTTP服务器连接
void stopConnect() {
  DebugPrintln("Disconnect");
  client.stop();
}
  
void clrEsp8266ResponseBuffer(void){
    memset(response, 0, MAX_CONTENT_SIZE);      //清空
}

6、TCP服务端(server)

  1. 8266作为WiFiServer端,打开TCP调试助手,模拟TCP Client的请求;
/**
 * Demo:
 *    演示WiFiServer功能
 *    打开TCP调试助手 模拟TCP client请求
 */
#include <ESP8266WiFi.h>
 
//定义最多多少个client可以连接本server(一般不要超过4个)
#define MAX_SRV_CLIENTS 1
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)
 
const char* ssid = "TP-LINK_5344";
const char* password = "6206908you11011010";
 
//创建server 端口号是23
WiFiServer server(23);
//管理clients
WiFiClient serverClients[MAX_SRV_CLIENTS];
 
void setup() {
  DebugBegin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  DebugPrint("\nConnecting to "); 
  DebugPrintln(ssid);
  uint8_t i = 0;
  while (WiFi.status() != WL_CONNECTED && i++ < 20) {
    delay(500);
  }
  if (i == 21) {
    DebugPrint("Could not connect to"); 
    DebugPrintln(ssid);
    while (1) {
      delay(500);
    }
  }
  //启动server
  server.begin();
  //关闭小包合并包功能,不会延时发送数据
  server.setNoDelay(true);
 
  DebugPrint("Ready! Use 'telnet ");
  DebugPrint(WiFi.localIP());
  DebugPrintln(" 23' to connect");
}
 
void loop() {
  uint8_t i;
  //检测是否有新的client请求进来
  if (server.hasClient()) {
    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
      //释放旧无效或者断开的client
      if (!serverClients[i] || !serverClients[i].connected()) {
        if (serverClients[i]) {
          serverClients[i].stop();
        }
        //分配最新的client
        serverClients[i] = server.available();
        DebugPrint("New client: "); 
        DebugPrint(i);
        break;
      }
    }
    //当达到最大连接数 无法释放无效的client,需要拒绝连接
    if (i == MAX_SRV_CLIENTS) {
      WiFiClient serverClient = server.available();
      serverClient.stop();
      DebugPrintln("Connection rejected ");
    }
  }
  //检测client发过来的数据
  for (i = 0; i < MAX_SRV_CLIENTS; i++) {
    if (serverClients[i] && serverClients[i].connected()) {
      if (serverClients[i].available()) {
        //get data from the telnet client and push it to the UART
        while (serverClients[i].available()) {
          //发送到串口调试器
          Serial.write(serverClients[i].read());
        }
      }
    }
  }
 
  if (Serial.available()) {
    //把串口调试器发过来的数据 发送给client
    size_t len = Serial.available();
    uint8_t sbuf[len];
    Serial.readBytes(sbuf, len);
    //push UART data to all connected telnet clients
    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
      if (serverClients[i] && serverClients[i].connected()) {
        serverClients[i].write(sbuf, len);
        delay(1);
      }
    }
  }
}
  1. 8266作为web server端,打开PC浏览器输入IP网址,请求web server
/**
 * Demo:
 *    演示web Server功能
 *    打开PC浏览器 输入IP地址。请求web server
 */
#include <ESP8266WiFi.h>
 
const char* ssid = "TP-LINK_5344";//wifi账号 这里需要修改
const char* password = "xxxx";//wifi密码 这里需要修改
 
//创建 tcp server 端口号是80
WiFiServer server(80);
 
void setup(){
  Serial.begin(115200);
  Serial.println();
 
  Serial.printf("Connecting to %s ", ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected");
  //启动TCP 连接
  server.begin();
  //打印TCP server IP地址
  Serial.printf("Web server started, open %s in a web browser\n", WiFi.localIP().toString().c_str());
}
 
/**
 * 模拟web server 返回http web响应内容
 * 这里是手动拼接HTTP响应内容
 * 后面楼主会继续讲解另外两个专用于http请求的库
 */
String prepareHtmlPage(){
  String htmlPage =
     String("HTTP/1.1 200 OK\r\n") +
            "Content-Type: text/html\r\n" +
            "Connection: close\r\n" +  // the connection will be closed after completion of the response
            "Refresh: 5\r\n" +  // refresh the page automatically every 5 sec
            "\r\n" +
            "<!DOCTYPE HTML>" +
            "<html>" +
            "Analog input:  " + String(analogRead(A0)) +
            "</html>" +
            "\r\n";
  return htmlPage;
}
 
 
void loop(){
  WiFiClient client = server.available();
  // wait for a client (web browser) to connect
  if (client){
    Serial.println("\n[Client connected]");
    while (client.connected()){
      // 不断读取请求内容
      if (client.available()){
        String line = client.readStringUntil('\r');
        Serial.print(line);
        // wait for end of client's request, that is marked with an empty line
        if (line.length() == 1 && line[0] == '\n'){
          //返回响应内容
          client.println(prepareHtmlPage());
          break;
        }
      }
      //由于我们设置了 Connection: close  当我们响应数据之后就会自动断开连接
    }
    delay(100); // give the web browser time to receive the data
 
    // close the connection:
    client.stop();
    Serial.println("[Client disonnected]");
  }
}
  1. 8266作为WiFiServer端,演示简单的web server功能,web server 会根据请求来做不同的操作
/*
* Demo:
*    演示简单web Server功能
*    web server会根据请求来做不同的操作
*    http://server_ip/gpio/0 打印 /gpio0
*    http://server_ip/gpio/1 打印 /gpio1
*    server_ip就是ESP8266的Ip地址
*/
 
#include <ESP8266WiFi.h>
 
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)
 
const char* ssid = "TP-LINK_5344";//wifi账号 这里需要修改
const char* password = "xxxx";//wifi密码 这里需要修改
 
// 创建tcp server
WiFiServer server(80);
 
void setup() {
  DebugBegin(115200);
  delay(10);
 
  // Connect to WiFi network
  DebugPrintln("");
  DebugPrintln(String("Connecting to ") + ssid);
  //我只想做个安静的美男子 STA
  WiFi.mode(WIFI_STA);
  //我想连接路由wifi
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    DebugPrint(".");
  }
  DebugPrintln("");
  DebugPrintln("WiFi connected");
 
  // 启动server
  server.begin();
  DebugPrintln("Server started");
 
  // 打印IP地址
  DebugPrintln(WiFi.localIP().toString());
}
 
void loop() {
  // 等待有效的tcp连接
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
 
  DebugPrintln("new client");
  //等待client数据过来
  while (!client.available()) {
    delay(1);
  }
 
  // 读取请求的第一行 会包括一个url,这里只处理url
  String req = client.readStringUntil('\r');
  DebugPrintln(req);
  //清掉缓冲区数据 据说这个方法没什么用 可以换种实现方式
  client.flush();
 
  // 开始匹配
  int val;
  if (req.indexOf("/gpio/0") != -1) {
    DebugPrintln("/gpio0");
    val = 0;
  } else if (req.indexOf("/gpio/1") != -1) {
    DebugPrintln("/gpio1");
    val = 1;
  } else {
    DebugPrintln("invalid request");
    //关闭这个client请求
    client.stop();
    return;
  }
  //清掉缓冲区数据
  client.flush();
 
  // 准备响应数据
  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nGPIO is now ";
  s += (val) ? "high" : "low";
  s += "</html>\n";
 
  // 发送响应数据给client
  client.print(s);
  delay(1);
  DebugPrintln("Client disonnected");
 
  // The client will actually be disconnected
  // when the function returns and 'client' object is detroyed
}

7、Smartconfig智能配网:

收集APP端发送包含WIFI用户名和密码的UDP广播包,智能终端的WIFI芯片接收到UDP包,解密配置连接。

手机软件esptouch:

#include <ESP8266WiFi.h>
 
void smartConfig()
{
  WiFi.mode(WIFI_STA);
  Serial.println("\r\nWait for Smartconfig");
  delay(2000);
  // 等待配网
  WiFi.beginSmartConfig();
 
 while (1)
  {
    Serial.print(".");
    delay(500);
    if (WiFi.smartConfigDone())
    {
      Serial.println("SmartConfig Success");
      Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
      Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
      WiFi.setAutoConnect(true);  // 设置自动连接
      break;
    }
  }
 
  Serial.println("");
  Serial.println("WiFi connected");  
 
}
 
void setup()
{
  Serial.begin(115200);
  smartConfig();
}
 
void loop()
{
  delay(1000);
   Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

文章作者: 旧时南风
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 旧时南风 !
评论
  目录