1. 前言

    在前面的博文中,博主介绍到ESP8266WiFi库是包含了很多功能的一个超级库。ESP8266WiFi库不仅仅局限于 ESP8266WiFi.hESP8266WiFi.cpp 这两个文件,只不过它们是最核心的统一入口。
    而在这些库中,有个8266模块通用库 ESP8266WiFiGeneric库,ESP8266WiFiSTA/ESP8266WiFiAP/ESP8266WiFiScan都会在它的基础上去做一些自己的逻辑(也就是会用到它的一些方法),所以算是比较重要的一个基础库,它包括处理程序来管理wi-fi事件,如连接,断开连接或获得ip,wi-fi模式的变化,管理模块睡眠模式的功能,以ip地址解析的hostName等;
    ESP8266在使用过程中并非会一直如希望般稳定运行的,为了应对这些情况就需要能够了解WiFi状态,并对WiFi突发事件作出响应。

2. ESP8266WiFiGeneric库

    首先,我们先看一下它的头文件源码:

class ESP8266WiFiGenericClass {
        // ----------------------------------------------------------------------------------------------
        // -------------------------------------- Generic WiFi function ---------------------------------
        // ----------------------------------------------------------------------------------------------

    public:
        ESP8266WiFiGenericClass();

        // Note: this function is deprecated. Use one of the functions below instead.
        void onEvent(WiFiEventCb cb, WiFiEvent_t event = WIFI_EVENT_ANY) __attribute__((deprecated));

        // Subscribe to specific event and get event information as an argument to the callback
        WiFiEventHandler onStationModeConnected(std::function<void(const WiFiEventStationModeConnected&)>);
        WiFiEventHandler onStationModeDisconnected(std::function<void(const WiFiEventStationModeDisconnected&)>);
        WiFiEventHandler onStationModeAuthModeChanged(std::function<void(const WiFiEventStationModeAuthModeChanged&)>);
        WiFiEventHandler onStationModeGotIP(std::function<void(const WiFiEventStationModeGotIP&)>);
        WiFiEventHandler onStationModeDHCPTimeout(std::function<void(void)>);
        WiFiEventHandler onSoftAPModeStationConnected(std::function<void(const WiFiEventSoftAPModeStationConnected&)>);
        WiFiEventHandler onSoftAPModeStationDisconnected(std::function<void(const WiFiEventSoftAPModeStationDisconnected&)>);
        WiFiEventHandler onSoftAPModeProbeRequestReceived(std::function<void(const WiFiEventSoftAPModeProbeRequestReceived&)>);
        // WiFiEventHandler onWiFiModeChange(std::function<void(const WiFiEventModeChange&)>);

        int32_t channel(void);

        bool setSleepMode(WiFiSleepType_t type);
        WiFiSleepType_t getSleepMode();

        bool setPhyMode(WiFiPhyMode_t mode);
        WiFiPhyMode_t getPhyMode();

        void setOutputPower(float dBm);

        void persistent(bool persistent);

        bool mode(WiFiMode_t);
        WiFiMode_t getMode();

        bool enableSTA(bool enable);
        bool enableAP(bool enable);

        bool forceSleepBegin(uint32 sleepUs = 0);
        bool forceSleepWake();

    protected:
        static bool _persistent;
        static WiFiMode_t _forceSleepLastMode;

        static void _eventCallback(void *event);

        // ----------------------------------------------------------------------------------------------
        // ------------------------------------ Generic Network function --------------------------------
        // ----------------------------------------------------------------------------------------------

    public:

        int hostByName(const char* aHostname, IPAddress& aResult);
        int hostByName(const char* aHostname, IPAddress& aResult, uint32_t timeout_ms);
        bool getPersistent();
    protected:

        friend class ESP8266WiFiSTAClass;
        friend class ESP8266WiFiScanClass;
        friend class ESP8266WiFiAPClass;
};

    这里出现了友元类(friend class),意味着 ESP8266WiFiSTAClassESP8266WiFiScanClassESP8266WiFiAPClass 可以访问 ESP8266WiFiGenericClass的private和protected成员。

    讲解之前,先浏览一下博主整理的百度脑图,以便有个整体认识:

整体上来说,方法可以分为两类:

  • 第一类方法,管理WIFi事件(WiFiEvent);
  • 第二类方法,与WiFi模式相关;

2.1 管理WIFi事件(WiFiEvent)

    首先我们需要了解一下有哪些WiFi事件,请打开源码中的 ESP8266WiFiType.h 文件,里面有关于WiFi事件的定义:

typedef enum WiFiEvent
{
    WIFI_EVENT_STAMODE_CONNECTED = 0,//STA模式下连接上网络
    WIFI_EVENT_STAMODE_DISCONNECTED,//STA模式下断开网络
    WIFI_EVENT_STAMODE_AUTHMODE_CHANGE,//STA模式下校验模式改变
    WIFI_EVENT_STAMODE_GOT_IP,//STA模式下模块获取到IP地址
    WIFI_EVENT_STAMODE_DHCP_TIMEOUT,//STA模式下DHCP分配IP超时
    WIFI_EVENT_SOFTAPMODE_STACONNECTED,//AP模式下有station连接进来
    WIFI_EVENT_SOFTAPMODE_STADISCONNECTED,//AP模式下有station断开连接
    WIFI_EVENT_SOFTAPMODE_PROBEREQRECVED,//AP模式下收到探针请求
    WIFI_EVENT_MAX,
    WIFI_EVENT_ANY = WIFI_EVENT_MAX,
    WIFI_EVENT_MODE_CHANGE //源码中已经去掉
} WiFiEvent_t;

    知道了有哪些事件(WiFiEvent),然后针对性去监听这些事件。当事件发生的时候,我们注册事件处理者(WiFiEventHandler),然后可以获取事件信息。
    使用WiFiEventHandler需要先声明,然后注册对应事件并加入事件触发时执行的操作:

//请注意,以下为伪代码,不能运行,注意理解思想即可
//声明事件
WiFiEventHandler event;

//事件触发时处理者
void handler(const WiFiEvent& event)
{
    //TODO 在这里可以获取具体的事件信息
}

//注册事件
event = WiFi.onWiFiEvent(handler);

2.1.1 onStationModeConnected —— STA模式下连接上网络

函数说明:

/**
 * 注册事件处理器
 * 事件类型:STA模式下连接上网络
 * @param 事件处理回调函数(函数的入参是 WiFiEventStationModeConnected)
 * @return WiFiEventHandler
 */
WiFiEventHandler onStationModeConnected(std::function<void(const WiFiEventStationModeConnected&)>);

注意点:

  • 每一次有station连接进来都会回调事件处理函数;

WiFiEventStationModeConnected 事件信息:

// WiFiEventStationModeConnected事件信息
struct WiFiEventStationModeConnected
{
    String ssid;// station的ssid,理解为名字
    uint8 bssid[6];//station的mac地址
    uint8 channel;//station连到的信道
};

2.1.2 onStationModeDisconnected —— STA模式下断开网络

函数说明:

/**
 * 注册事件处理器
 * 事件类型:STA模式下断开网络
 * @param 事件处理回调函数(函数的入参是 WiFiEventStationModeDisconnected)
 * @return WiFiEventHandler
 */
WiFiEventHandler onStationModeDisconnected(std::function<void(const WiFiEventStationModeDisconnected&)>);

注意点:

  • 每一次有station断开连接都会回调事件处理函数;

WiFiEventStationModeDisconnected 事件信息:

// WiFiEventStationModeDisconnected 事件信息
struct WiFiEventStationModeDisconnected
{
    String ssid;// station的ssid,理解为名字
    uint8 bssid[6];//station的mac地址
    WiFiDisconnectReason reason;//断开连接原因
};

//断开连接原因
enum WiFiDisconnectReason
{
    WIFI_DISCONNECT_REASON_UNSPECIFIED              = 1,
    WIFI_DISCONNECT_REASON_AUTH_EXPIRE              = 2,
    WIFI_DISCONNECT_REASON_AUTH_LEAVE               = 3,
    WIFI_DISCONNECT_REASON_ASSOC_EXPIRE             = 4,
    WIFI_DISCONNECT_REASON_ASSOC_TOOMANY            = 5,
    WIFI_DISCONNECT_REASON_NOT_AUTHED               = 6,
    WIFI_DISCONNECT_REASON_NOT_ASSOCED              = 7,
    WIFI_DISCONNECT_REASON_ASSOC_LEAVE              = 8,
    WIFI_DISCONNECT_REASON_ASSOC_NOT_AUTHED         = 9,
    WIFI_DISCONNECT_REASON_DISASSOC_PWRCAP_BAD      = 10,  /* 11h */
    WIFI_DISCONNECT_REASON_DISASSOC_SUPCHAN_BAD     = 11,  /* 11h */
    WIFI_DISCONNECT_REASON_IE_INVALID               = 13,  /* 11i */
    WIFI_DISCONNECT_REASON_MIC_FAILURE              = 14,  /* 11i */
    WIFI_DISCONNECT_REASON_4WAY_HANDSHAKE_TIMEOUT   = 15,  /* 11i */
    WIFI_DISCONNECT_REASON_GROUP_KEY_UPDATE_TIMEOUT = 16,  /* 11i */
    WIFI_DISCONNECT_REASON_IE_IN_4WAY_DIFFERS       = 17,  /* 11i */
    WIFI_DISCONNECT_REASON_GROUP_CIPHER_INVALID     = 18,  /* 11i */
    WIFI_DISCONNECT_REASON_PAIRWISE_CIPHER_INVALID  = 19,  /* 11i */
    WIFI_DISCONNECT_REASON_AKMP_INVALID             = 20,  /* 11i */
    WIFI_DISCONNECT_REASON_UNSUPP_RSN_IE_VERSION    = 21,  /* 11i */
    WIFI_DISCONNECT_REASON_INVALID_RSN_IE_CAP       = 22,  /* 11i */
    WIFI_DISCONNECT_REASON_802_1X_AUTH_FAILED       = 23,  /* 11i */
    WIFI_DISCONNECT_REASON_CIPHER_SUITE_REJECTED    = 24,  /* 11i */

    WIFI_DISCONNECT_REASON_BEACON_TIMEOUT           = 200,
    WIFI_DISCONNECT_REASON_NO_AP_FOUND              = 201,
    WIFI_DISCONNECT_REASON_AUTH_FAIL                = 202,
    WIFI_DISCONNECT_REASON_ASSOC_FAIL               = 203,
    WIFI_DISCONNECT_REASON_HANDSHAKE_TIMEOUT        = 204,
};

2.1.3 onStationModeAuthModeChanged —— STA模式下校验模式改变

函数说明:

/**
 * 注册事件处理器
 * 事件类型:STA模式下校验模式改变
 * @param 事件处理回调函数(函数的入参是 WiFiEventStationModeAuthModeChanged)
 * @return WiFiEventHandler
 */
WiFiEventHandler onStationModeAuthModeChanged(std::function<void(const WiFiEventStationModeAuthModeChanged&)>);

注意点:

  • 每一次验证模式都会回调事件处理函数;

WiFiEventStationModeAuthModeChanged 事件信息:

// WiFiEventStationModeAuthModeChanged 事件信息
struct WiFiEventStationModeAuthModeChanged
{
    uint8 oldMode;
    uint8 newMode;
};

验证模式:

typedef enum _auth_mode {
    AUTH_OPEN           = 0,
    AUTH_WEP,
    AUTH_WPA_PSK,
    AUTH_WPA2_PSK,
    AUTH_WPA_WPA2_PSK,
    AUTH_MAX
} AUTH_MODE;

2.1.4 onStationModeGotIP —— STA模式下模块获取到IP地址

函数说明:

/**
 * 注册事件处理器
 * 事件类型:STA模式下模块获取到IP地址
 * @param 事件处理回调函数(函数的入参是 WiFiEventStationModeGotIP)
 * @return WiFiEventHandler
 */
WiFiEventHandler onStationModeGotIP(std::function<void(const WiFiEventStationModeGotIP&)>);

WiFiEventStationModeGotIP 事件信息:

// WiFiEventStationModeGotIP 事件信息
struct WiFiEventStationModeGotIP
{
    IPAddress ip;//IP地址
    IPAddress mask;//子网掩码
    IPAddress gw;//网关
};

2.1.5 onStatioonStationModeDHCPTimeout nModeConnected —— STA模式下DHCP分配IP超时

函数说明:

/**
 * 注册事件处理器
 * 事件类型:STA模式下DHCP分配IP超时
 * @param 事件处理回调函数
 * @return WiFiEventHandler
 */
WiFiEventHandler onStationModeDHCPTimeout(std::function<void(void)>);

注意点:

  • 关于这一点,博主也没有试过;

2.1.6 onSoftAPModeStationConnected —— AP模式下有station连接进来

函数说明:

/**
 * 注册事件处理器
 * 事件类型:AP模式下有station连接进来
 * @param 事件处理回调函数(函数的入参是 WiFiEventSoftAPModeStationConnected)
 * @return WiFiEventHandler
 */
WiFiEventHandler onSoftAPModeStationConnected(std::function<void(const WiFiEventSoftAPModeStationConnected&)>);

WiFiEventSoftAPModeStationConnected 事件信息:

// WiFiEventSoftAPModeStationConnected 事件信息
struct WiFiEventSoftAPModeStationConnected
{
    uint8 mac[6];//station mac地址
    uint8 aid;// station 名字
};

2.1.7 onSoftAPModeStationDisconnected —— AP模式下有station断开连接

函数说明:

/**
 * 注册事件处理器
 * 事件类型:AP模式下有station断开连接
 * @param 事件处理回调函数(函数的入参是 WiFiEventSoftAPModeStationDisconnected)
 * @return WiFiEventHandler
 */
WiFiEventHandler onSoftAPModeStationDisconnected(std::function<void(const WiFiEventSoftAPModeStationDisconnected&)>);

WiFiEventSoftAPModeStationDisconnected 事件信息:

// WiFiEventSoftAPModeStationDisconnected 事件信息
struct WiFiEventSoftAPModeStationDisconnected
{
    uint8 mac[6];//station mac地址
    uint8 aid;// station 名字
};

2.1.8 onSoftAPModeProbeRequestReceived —— AP模式下收到探针请求

函数说明:

/**
 * 注册事件处理器
 * 事件类型:AP模式下收到探针请求
 * @param 事件处理回调函数(函数的入参是 WiFiEventSoftAPModeProbeRequestReceived)
 * @return WiFiEventHandler
 */
WiFiEventHandler onSoftAPModeProbeRequestReceived(std::function<void(const WiFiEventSoftAPModeProbeRequestReceived&)>);

WiFiEventSoftAPModeProbeRequestReceived 事件信息:

// WiFiEventSoftAPModeStationDisconnected 事件信息
struct WiFiEventSoftAPModeProbeRequestReceived
{
    int rssi;//信号强度
    uint8 mac[6];//mac地址
};

2.2 与WiFi配置模式相关

2.2.1 persistent —— 是否保存wifi设置到flash中

函数说明:

/**
 * 是否保存wifi设置到flash中
 * @param persistent 该参数设置是否将WiFi参数保存于Flash中,默认为true
 */
void persistent(bool persistent);

注意点:

  • 该方法设置是否将WiFi参数保存于Flash中,默认为true,即在每次调用 WiFi.begin()、WiFi.softAP()、WiFi.disconnect、WiFi.softAPdisconnect 方法时都会将相关数据写入到Flash中;
  • 如果使用该方法设置为false时,以上动作将不会把数据写入Flash中,仅仅改变内存中的WiFi设置;

2.2.1 mode —— 设置wifi工作模式

函数说明:

/**
 * 设置wifi工作模式
 * @param WiFiMode_t wifi工作模式
 * @return bool 是否设置成功
 */
bool mode(WiFiMode_t);

WiFi工作模式:

typedef enum WiFiMode
{
    WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3
} WiFiMode_t;

读者是不是感觉上面的枚举很熟悉呢?

2.2.2 getMode —— 获取当前wifi工作模式

函数说明:

/**
 * 获取当前wifi工作模式
 * @return WiFiMode_t 当前wifi工作模式
 */
WiFiMode_t getMode();

2.2.3 enableSTA —— 设置为STA模式

函数说明:

/**
 * 设置为STA模式
 * @param enable true表示使能STA工作模式
 * @return bool 是否设置成功
 */
bool enableSTA(bool enable);

注意点:

  • 底层代码其实是调用mode()方法;

2.2.4 enableAP —— 设置为AP模式

函数说明:

/**
 * 设置为AP模式
 * @param enable true表示使能AP工作模式
 * @return bool 是否设置成功
 */
bool enableAP(bool enable);

注意点:

  • 底层代码其实是调用mode()方法;

2.2.5 setSleepMode —— 设置睡眠模式

函数说明:

/**
 * 设置睡眠模式
 * @param WiFiSleepType_t 睡眠模式
 * @return bool 是否设置成功
 */
bool setSleepMode(WiFiSleepType_t type);

WiFiSleepType_t 睡眠模式:

typedef enum WiFiSleepType
{
    WIFI_NONE_SLEEP = 0,//非睡眠模式 WIFI_LIGHT_SLEEP = 1,//轻度睡眠 WIFI_MODEM_SLEEP = 2//深度睡眠
} WiFiSleepType_t;

注意点:

  • 睡眠模式是一个比较大的知识,这里略讲;

3. 实例操作

3.1 官方示例

源码:

/*
    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);
}

3.2 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(); //断开当前网络连接
}

4. 总结

    本篇博文更注重于讲解WiFi通信过程中的一些事件以及配置,可以增加开发者对于设备的了解,这对于开发稳定的产品是比较有帮助的。

ESP8266开发之旅 网络篇⑥ ESP8266WiFiGeneric——基础库的更多相关文章

  1. ESP8266开发之旅 网络篇⑨ HttpClient——ESP8266HTTPClient库的使用

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  2. ESP8266开发之旅 网络篇⑪ WebServer——ESP8266WebServer库的使用

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  3. ESP8266开发之旅 网络篇⑫ 域名服务——ESP8266mDNS库

    1. 前言     前面的博文中,无论是作为client端还是server端,它们之间的通信都是通过具体的IP地址来寻址.通过IP地址来寻址,本身就是一个弊端,用户怎么会去记住这些魔法数字呢?那么有没 ...

  4. ESP8266开发之旅 网络篇③ Soft-AP——ESP8266WiFiAP库的使用

    1. 前言     在前面的篇章中,博主给大家讲解了ESP8266的软硬件配置以及基本功能使用,目的就是想让大家有个初步认识.并且,博主一直重点强调 ESP8266 WiFi模块有三种工作模式: St ...

  5. ESP8266开发之旅 网络篇④ Station——ESP8266WiFiSTA库的使用

    1. 前言     在前面的篇章中,博主给大家讲解了ESP8266的软硬件配置以及基本功能使用,目的就是想让大家有个初步认识.并且,博主一直重点强调 ESP8266 WiFi模块有三种工作模式: St ...

  6. ESP8266开发之旅 网络篇⑯ 无线更新——OTA固件更新

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  7. ESP8266开发之旅 网络篇⑦ TCP Server & TCP Client

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  8. ESP8266开发之旅 网络篇⑧ SmartConfig——一键配网

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  9. ESP8266开发之旅 网络篇⑩ UDP服务

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

随机推荐

  1. .netCore+Vue 搭建的简捷开发框架

    话不多说,上图: 整体项目结构如图所示,我的设计初衷是基于.netCore + DI + Vue 打造一个适合初学者的简捷开发框架. 架构模型采用基于RESTful API风格的前后台分离框架,总体分 ...

  2. 快速获取dom到body左侧和顶部的距离,简单粗暴无bug-getBoundingClientRect

    获取dom到body左侧和顶部的距离-getBoundingClientRect 平时在写js的时候,偶尔会需要用js来获取当前div到 body 左侧.顶部的距离.网上查一查,有很多都是通过offs ...

  3. [LeetCode]singleNumber

    题目:singleNumber Given an array of integers, every element appears twice except for one. Find that si ...

  4. python中pyqt5的进度条--python实战(十)

    python太博大精深了,使用场景非常多.最近笔者一直使用PyQt5编一些小程序,顺便就把一些常用的东西列出来,做个记录和积累吧.进度条是非常常用的东西,今天用的时候,顺便温习了一下,这个东西自己感觉 ...

  5. 验证fstab文件修改是否正确

    /etc/fstab文件是系统启动时要挂载点文件系统. 如果fstab文件配置错误,会导致系统无法正常启动. 最近我就是因为大意,在配置fstab重启服务器后,出现系统无法识别挂载点/opt/back ...

  6. Spring boot 官网学习笔记 - Auto-configuration(@SpringBootApplication、@EnableAutoConfiguration、@Configuration)

    Spring Boot auto-configuration attempts to automatically configure your Spring application based on ...

  7. Julia初学备忘

    println("hello!") println("hello!") print("hello!") print("hello! ...

  8. java 队列和栈相互实现

    一.队列实现栈 public class queue2stack { public static void main(String[] args) { QS qs = new QS(); qs.pus ...

  9. java通过代理创建Conncection对象与自定义JDBC连接池

    最近学习了一下代理发现,代理其实一个蛮有用的,主要是用在动态的实现接口中的某一个方法而不去继承这个接口所用的一种技巧,首先是自定义的一个连接池 代码如下 import java.lang.reflec ...

  10. python 列表,集合,字典,字符串的使用

    PY PY基础 append 在末尾添加元素 pop 删除末尾元素 insert(i,item)在i位插入元素 pop(i)删除i位元素 只有1个元素的tuple定义时必须加一个逗号,,来消除歧义 i ...