07 - 网络通信

WiFi 与蓝牙连接配置

WiFi 连接

Station 模式 (连接路由器)

#include "esp_wifi.h"
#include "esp_event.h"
 
#define WIFI_SSID     "YourSSID"
#define WIFI_PASSWORD "YourPassword"
 
static void wifi_event_handler(void *event_handler_arg, esp_event_base_t event_base,
                                int32_t event_id, void *event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    }
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) {
        printf("WiFi connected\n");
    }
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
        printf("Got IP: " IPSTR "\n", IP2STR(&event->ip_info.ip));
    }
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        printf("WiFi disconnected, reconnecting...\n");
        esp_wifi_connect();
    }
}
 
void wifi_init_sta(void)
{
    esp_netif_init();
    esp_event_loop_create_default();
    esp_netif_create_default_wifi_sta();
 
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);
 
    esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL);
    esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler, NULL);
 
    wifi_config_t wifi_config = {
        .sta = {
            .threshold.authmode = WIFI_AUTH_WPA2_PSK,
        },
    };
    memcpy(wifi_config.sta.ssid, WIFI_SSID, strlen(WIFI_SSID));
    memcpy(wifi_config.sta.password, WIFI_PASSWORD, strlen(WIFI_PASSWORD));
 
    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
    esp_wifi_start();
 
    printf("WiFi started, connecting to %s...\n", WIFI_SSID);
}

SoftAP 模式 (建立热点)

void wifi_init_ap(void)
{
    esp_netif_init();
    esp_event_loop_create_default();
    esp_netif_create_default_wifi_softap();
 
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);
 
    wifi_config_t ap_config = {
        .ap = {
            .ssid = "ESP32_Config",
            .ssid_len = strlen("ESP32_Config"),
            .password = "12345678",
            .max_connection = 4,
            .authmode = WIFI_AUTH_WPA_WPA2_PSK
        }
    };
 
    esp_wifi_set_mode(WIFI_MODE_AP);
    esp_wifi_set_config(WIFI_IF_AP, &ap_config);
    esp_wifi_start();
 
    printf("AP started, SSID: ESP32_Config\n");
}

WiFi 扫描

void wifi_scan(void)
{
    wifi_scan_config_t scan_config = {
        .show_hidden = true,
        .scan_type = WIFI_SCAN_TYPE_ACTIVE,
        .scan_time.active.min = 100,
        .scan_time.active.max = 500
    };
 
    esp_wifi_scan_start(&scan_config, true);
 
    uint16_t ap_num = 20;
    wifi_ap_record_t ap_info[20];
    esp_wifi_scan_get_ap_records(&ap_num, ap_info);
 
    printf("Found %d networks:\n", ap_num);
    for (int i = 0; i < ap_num; i++) {
        printf("  %s  RSSI: %d\n", ap_info[i].ssid, ap_info[i].rssi);
    }
}

HTTP 客户端

GET 请求

#include "esp_http_client.h"
 
esp_err_t http_event_handler(esp_http_client_event_t *evt)
{
    switch (evt->event_id) {
        case HTTP_EVENT_ON_DATA:
            printf("%.*s\n", evt->data_len, (char *)evt->data);
            break;
        case HTTP_EVENT_ON_FINISH:
            printf("HTTP request finished\n");
            break;
        default:
            break;
    }
    return ESP_OK;
}
 
void http_get_request(void)
{
    esp_http_client_config_t config = {
        .url = "http://httpbin.org/get",
        .event_handler = http_event_handler
    };
 
    esp_http_client_handle_t client = esp_http_client_init(&config);
    esp_http_client_perform(client);
    esp_http_client_cleanup(client);
}

POST 请求

void http_post_request(void)
{
    const char *post_data = "{\"key\":\"value\"}";
 
    esp_http_client_config_t config = {
        .url = "http://httpbin.org/post",
        .method = HTTP_METHOD_POST,
        .event_handler = http_event_handler
    };
 
    esp_http_client_handle_t client = esp_http_client_init(&config);
    esp_http_client_set_header(client, "Content-Type", "application/json");
    esp_http_client_set_post_field(client, post_data, strlen(post_data));
 
    esp_http_client_perform(client);
    esp_http_client_cleanup(client);
}

MQTT

订阅与发布

#include "mqtt_client.h"
 
static esp_mqtt_client_handle_t mqtt_client;
 
static void mqtt_event_handler(void *handler_args, esp_event_base_t base,
                                int32_t event_id, void *event_data)
{
    esp_mqtt_event_handle_t event = (esp_mqtt_event_handle_t)event_data;
 
    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:
            printf("MQTT connected\n");
            esp_mqtt_client_subscribe(mqtt_client, "/topic/sub", 0);
            break;
        case MQTT_EVENT_DATA:
            printf("Topic: %.*s\n", event->topic_len, event->topic);
            printf("Data: %.*s\n", event->data_len, event->data);
            break;
        case MQTT_EVENT_DISCONNECTED:
            printf("MQTT disconnected\n");
            break;
    }
}
 
void mqtt_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
        .broker.address.uri = "mqtt://broker.emqx.io:1883",
        .credentials.client_id = "esp32_client"
    };
 
    mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    esp_mqtt_client_start(mqtt_client);
}
 
void mqtt_publish(const char *topic, const char *data)
{
    esp_mqtt_client_publish(mqtt_client, topic, data, 0, 1, 0);
}

常用 MQTT Broker

Broker地址端口
EMQXbroker.emqx.io1883
Mosquittotest.mosquitto.org1883
HiveMQbroker.hivemq.com1883

蓝牙低功耗 (BLE)

GATT 服务器

#include "esp_bt.h"
#include "esp_gatt_common_api.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
 
#define GATTS_SERVICE_UUID    0x00FF
#define GATTS_CHAR_UUID       0xFF01
 
static const uint8_t manufacturer[3] = {'E', 'S', 'P'};
 
static void gatts_profile_event_handler(esp_gatts_cb_event_t event,
                                         esp_gatt_if_t gatts_if,
                                         esp_ble_gatts_cb_param_t *param)
{
    switch (event) {
        case ESP_GATTS_REG_EVT:
            printf("GATT server registered\n");
            break;
        case ESP_GATTS_CREATE_ATTR_TABLE:
            printf("Attribute table created\n");
            break;
        case ESP_GATTS_READ_EVT: {
            printf("Read request, handle: %d\n", param->read.handle);
            esp_gatt_rsp_t rsp = {
                .attr_value.len = 3,
                .attr_value.value = {manufacturer[0], manufacturer[1], manufacturer[2]}
            };
            esp_ble_gatts_send_response(gatts_if, param->read.conn_id,
                                        param->read.trans_id, ESP_GATT_OK, &rsp);
            break;
        }
    }
}
 
void ble_gatts_init(void)
{
    esp_bluedroid_init();
    esp_bluedroid_enable();
    esp_ble_gatts_register_callback(gatts_profile_event_handler);
    esp_ble_gatts_app_register(0);
}

BLE 扫描

static void ble_scan_result(esp_ble_gap_cb_param_t *param)
{
    if (param->scan_rst.ble_adv && param->scan_rst.adv_name_len > 0) {
        printf("Found device: %.*s\n",
               param->scan_rst.adv_name_len,
               param->scan_rst.ble_adv->name);
    }
}
 
void ble_scan_start(void)
{
    esp_ble_gap_register_callback(ble_scan_result);
    esp_ble_gap_start_scanning(30);  // 扫描30秒
}

网络时间同步 (NTP)

#include "esp_sntp.h"
 
void sntp_init_time(void)
{
    esp_sntp_setoperatingmode(SNTP_OPMODE_POLL);
    esp_sntp_setservername(0, "pool.ntp.org");
    esp_sntp_setservername(1, "time.google.com");
 
    sntp_set_time_sync_notification_cb([](struct timeval *tv) {
        printf("Time synchronized!\n");
    });
 
    esp_sntp_init();
}
 
// 获取当前时间
void get_current_time(void)
{
    time_t now;
    struct tm timeinfo;
    time(&now);
    localtime_r(&now, &timeinfo);
 
    printf("Current time: %04d-%02d-%02d %02d:%02d:%02d\n",
           timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday,
           timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
}

参考资料

官方文档

技术参考

图片参考

ESP32 WiFi 网络架构


相关链接

反向链接

进阶学习


下一步