ESP32開発ノート(3)ソースコード例18_WIFI_AP_UDPソフトAPモードでUDP通信を実現

開発ボード購入リンク

https://item.taobao.com/item.htm?spm=a2oq0.12575281.0.0.50111deb2Ij1As&ft=t&id=626366733674

はじめに開発ボード用に
開発環境構築ウィンドウへ
:基本ルーチン
    0_Helloバグ(ESP_LOGXとprintfのは)     プロジェクトテンプレート/印刷出力のデバッグ
    1_LED                                                     コントロールのオンとオフLEDを       
    2_LED_Task                                           タスクモード使用して制御LED
    3_LEDC_PWM                                       制御するために使用LEDCを光効果呼吸達成するために、LED
    4_ADC_LightRの                                       読み取りに使用するADCをフォトレジスター、光センシング達成する
    5_KEY_Short_Longを                               達成するためにボタンを長押し、短押しを
    6_TouchPad_Interrupt                           達成するために、割り込み静電容量式タッチを
    7_WS2812_RMTを                                   RGB_LED虹色の例達成するために、RMTを使用
    する8_DHT11_RMT                                     DHT11温度を読み取るためにRMTを使用する湿度センサ
    9_SPI_SDCard                                     SPIバスTFカードファイルシステムを使用する例示的な実施
    10_IIC_ADXL345を                                 角度ADXL345加速度を読み取るためのIICバスを使用してセンサー
    11_IIC_AT24C02は                                  小容量データストレージを実現するためにIICバステストを用い
    12_IR_Rev_RMT                                 赤外線リモコン受信機デコーダを使用しては、RMT(NEC符号化)実施
    13_IR_Send_RMTを                               赤外線データ伝送を使用しては、RMTを実装しました(NECコード)
    14_WIFI_Scan                                     WIFI信号走査例近く    
    15_WIFI_AP                                         ソフトAP例作成
    16_WIFI_AP_TCP_Server                   TCPサーバを実現する                   ソフトAPモードでは
    17_WIFI_AP_TCP_Clientは TCPクライアントを実現するソフトAPモードで
    18_WIFI_AP_UDP                              ソフトAPモードUDP通信で達成
    19_WIFI_STA                                       ルータに接続されたSTAスレーブモード作成
    20_WIFI_STA_TCP_Server                 スレーブモードSTAでTCPサーバを実装
    21_WIFI_STA_TCP_Client                 スレーブモードSTA TCPクライアントに実装
    22_WIFI_STA_UDP                             UDP通信モードSTAスレーブ実装
    23_LCD_TestをLCD液晶タッチスクリーンディスプレイ・テストを 
    24_LVGL_Test LVGLグラフィックライブラリの簡単な例

APモードの紹介

アクセスポイント(AP)は、Wi-Fiネットワークアクセスを提供し、有線ネットワークに接続するデバイスです。有線ネットワークとのインターフェースがないことに加えて、ESP32は同様の機能を提供できます。この動作モードは、ソフトアクセスポイント(soft-AP)と呼ばれます。ソフトAPに同時に接続できるステーションの最大数は4に設定でき、デフォルトは4です。

ESP32がAPモードのみの場合、外部ネットワークにアクセスできないLAN WiFiルーターノードと見なすことができ、さまざまなデバイスからの接続要求を受け入れることができます。また、TCPおよびUDPを介して接続デバイスと接続して、データフローを実現できます。ローカルのモノのインターネットの設計において、データ受信ノードおよび送信ノードの役割を果たすことができます。

UDPプロトコルの概要

UDP(ユーザーデータグラムプロトコル、ユーザーデータグラムプロトコル)
UDPはトランスポート層プロトコルであり、その機能は、IPデータグラムサービスに最も基本的なサービス(多重化と逆多重化、およびエラー検出)を追加することです。

UDPは信頼性の低いサービスを提供し、TCPにはない利点があります。

UDPには接続がなく、接続を確立するために必要な時間遅延はありません。空間的には、TCPはエンドシステムの接続状態を維持する必要があるため、ある程度のオーバーヘッドが必要です。この接続は、受信バッファーと送信バッファー、輻輳制御パラメーター、シーケンス番号と確認番号などのパラメーターをロードします。UCPは接続状態を維持せず、これらのパラメーターも追跡しないため、オーバーヘッドは小さくなります。空間と時間の両方に利点があります。
例えば:

DNSがUDPではなくTCPで実行されている場合、DNSの速度ははるかに遅くなります。
HTTPはUDPではなくTCPを使用します。これは、テキストデータに基づくWebページでは信頼性が非常に重要であるためです。
同じ種類の専用アプリケーションサーバーがUDPをサポートする場合、よりアクティブなクライアントをサポートできる必要があります。

パケットヘッダーのオーバーヘッドは小さい**、TCPヘッダーは20バイト、UDPヘッダーは8バイトです。

UDPには輻輳制御がありません。アプリケーション層は、送信するデータと送信時間をより適切に制御できます。ネットワークの輻輳制御は、ホストの送信速度に影響しません。特定のリアルタイムアプリケーションは、安定した速度での送信を必要とします。これにより、ある程度のデータ損失は許容できますが、大きな遅延は許されません(リアルタイムビデオ、ライブブロードキャストなど)。

UDPはベストエフォート型の配信を提供し、信頼できる配信を保証するものではありません。伝送の信頼性を維持するためのすべての作業では、ユーザーがアプリケーション層で完了する必要があります。TCP確認メカニズムまたは再送信メカニズムはありません。ネットワーク上の理由で相手側に送信されない場合、UDPはアプリケーション層にエラーメッセージを返しません。

UDPはメッセージ指向です。アプリケーション層から受け渡されるメッセージの場合、ヘッダーが追加され、直接IP層に配信されます。ヘッダーはマージも分割もされず、これらのメッセージの境界を保持します。IP層に配信されたUDPユーザーデータグラムは、ヘッダーが削除された後もそのまま上位のアプリケーションプロセスに配信され、メッセージは分割できず、UDPデータグラム処理の最小単位です。
このため、UDPはデータの読み取りと書き込みの頻度と量を制御するのに十分な柔軟性を備えていません。たとえば、100バイトのメッセージを送信する場合、sendto関数を1回呼び出して100バイトを送信し、反対側の端もrecvfrom関数を使用して一度に100バイトを受信する必要があります。ループを使用して毎回10バイトを取得することはできません。これを10回繰り返します。

UDPは、DNS、SNMPなど、一度に比較的少量のデータを送信するネットワークアプリケーションで一般的に使用されます。これらのアプリケーションでは、TCPを使用すると、接続の作成、メンテナンス、および破棄に多くのオーバーヘッドが発生するためです。UDPは、マルチメディアアプリケーション(IPテレフォニー、リアルタイムビデオ会議、ストリーミングメディアなど)でもよく使用されます。データの信頼性の高い伝送は、それらにとって重要ではありません。TCPの輻輳制御は、それらに大きな遅延を生じさせ、これも耐えられません。

実験プロセス

1. ESP32でAPを作成します

2. UDPリスナーを作成する

3.コンピュータ/携帯電話がこのESP32によって作成されたAPに接続するのを待ちます

4.コンピューター/携帯電話のUDPがメッセージを送信するのを待ち、そのままメッセージを返します。

1つは、コードを書く

最初に必要なヘッダーファイルを引用します

#include <stdio.h>
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_err.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include <string.h>
#include <sys/socket.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"

メイン関数を書く

// 主函数
void app_main(void)
{
	ESP_LOGI(TAG, "APP Start......");
	//初始化flash
	esp_err_t ret = nvs_flash_init();
	if (ret == ESP_ERR_NVS_NO_FREE_PAGES){
		ESP_ERROR_CHECK(nvs_flash_erase());
		ret = nvs_flash_init();
	}
	ESP_ERROR_CHECK(ret);
	wifi_init_softap();
	//新建一个udp连接任务
    xTaskCreate(&udp_connect, "udp_connect", 4096, NULL, 5, NULL);
}

AP機能を作成

// WIFI作为AP的初始化
void wifi_init_softap()
{
	udp_event_group = xEventGroupCreate();
	tcpip_adapter_init();
	ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
	wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
	ESP_ERROR_CHECK(esp_wifi_init(&cfg));
	wifi_config_t wifi_config = {
		.ap = {
			.ssid = SOFT_AP_SSID,
			.password = SOFT_AP_PAS,
			.ssid_len = 0,
			.max_connection = SOFT_AP_MAX_CONNECT,
			.authmode = WIFI_AUTH_WPA_WPA2_PSK,
		},
	};
	if (strlen(SOFT_AP_PAS) == 0){
		wifi_config.ap.authmode = WIFI_AUTH_OPEN;
	}
	ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP) );
	ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
	ESP_ERROR_CHECK(esp_wifi_start());
	ESP_LOGI(TAG, "SoftAP set finish,SSID:%s password:%s \n",wifi_config.ap.ssid, wifi_config.ap.password);
}

UDP接続タスク

// 建立UDP连接并从UDP接收数据
static void udp_connect(void *pvParameters)
{
	//等待WIFI连接成功事件,死等
	xEventGroupWaitBits(udp_event_group, WIFI_CONNECTED_BIT, false, true, portMAX_DELAY);
	ESP_LOGI(TAG, "start udp connected");
	vTaskDelay(3000 / portTICK_RATE_MS);
	ESP_LOGI(TAG, "create udp Client");
	int socket_ret = create_udp_client();
	if (socket_ret == ESP_FAIL){
		ESP_LOGI(TAG, "create udp socket error,stop...");
		vTaskDelete(NULL);
	}else{
		ESP_LOGI(TAG, "create udp socket succeed...");            
		//建立UDP接收数据任务
		if (pdPASS != xTaskCreate(&recv_data, "recv_data", 4096, NULL, 4, NULL)){
			ESP_LOGI(TAG, "Recv task create fail!");
			vTaskDelete(NULL);
		}else{
			ESP_LOGI(TAG, "Recv task create succeed!");
		}
	}
	vTaskDelete(NULL);
}

UDP関数を作成する

// 建立udp client
esp_err_t create_udp_client()
{
	ESP_LOGI(TAG, "will connect gateway ssid : %s port:%d",UDP_ADRESS, UDP_PORT);
	//新建socket
	connect_socket = socket(AF_INET, SOCK_DGRAM, 0);                         /*参数和TCP不同*/
	if (connect_socket < 0){
		//打印报错信息
		show_socket_error_reason("create client", connect_socket);
		//新建失败后,关闭新建的socket,等待下次新建
		close(connect_socket);
		return ESP_FAIL;
	}
	//配置连接服务器信息
	client_addr.sin_family = AF_INET;
	client_addr.sin_port = htons(UDP_PORT);
	client_addr.sin_addr.s_addr = inet_addr(UDP_ADRESS);

	struct sockaddr_in Loacl_addr; 
	Loacl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	Loacl_addr.sin_family = AF_INET;
	Loacl_addr.sin_port = htons(UDP_PORT); //设置本地端口
	uint8_t res = 0;
	res = bind(connect_socket,(struct sockaddr *)&Loacl_addr,sizeof(Loacl_addr));
	if(res != 0){
		printf("bind error\n");

	}



	int len = 0;            //长度
	char databuff[1024] = "Hello Server,Please ack!!";    //缓存
	//测试udp server
	len = sendto(connect_socket, databuff, 1024, 0, (struct sockaddr *) &client_addr,sizeof(client_addr));
	if (len > 0) {
		ESP_LOGI(TAG, "Transfer data to %s:%u,ssucceed\n",inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
	} else {
		show_socket_error_reason("recv_data", connect_socket);
		close(connect_socket);
		return ESP_FAIL;
	}
	return ESP_OK;
}

データタスクの受信と処理

// 接收数据任务
void recv_data(void *pvParameters)
{
	int len = 0;            //长度
	char databuff[1024];    //缓存
	while (1){
		memset(databuff, 0x00, sizeof(databuff));//清空缓存
		//读取接收数据
		len = recvfrom(connect_socket, databuff, sizeof(databuff), 0,(struct sockaddr *) &client_addr, &socklen);
		if (len > 0){
			//打印接收到的数组
			ESP_LOGI(TAG, "UDP Client recvData: %s", databuff);
			//接收数据回发
			sendto(connect_socket, databuff, strlen(databuff), 0,(struct sockaddr *) &client_addr, sizeof(client_addr));
		}else{
			//打印错误信息
			show_socket_error_reason("UDP Client recv_data", connect_socket);
			break;
		}
	}
	close_socket();
	vTaskDelete(NULL);
}

WIFIイベント処理

// wifi 事件
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    switch (event->event_id)
    {
	case SYSTEM_EVENT_AP_STACONNECTED:  //AP模式-有STA连接成功
		//作为ap,有sta连接
		ESP_LOGI(TAG, "station:" MACSTR " join,AID=%d\n",MAC2STR(event->event_info.sta_connected.mac),event->event_info.sta_connected.aid);
		xEventGroupSetBits(udp_event_group, WIFI_CONNECTED_BIT);
		break;
	case SYSTEM_EVENT_AP_STADISCONNECTED://AP模式-有STA断线
		ESP_LOGI(TAG, "station:" MACSTR "leave,AID=%d\n",MAC2STR(event->event_info.sta_disconnected.mac),event->event_info.sta_disconnected.aid);
		xEventGroupClearBits(udp_event_group, WIFI_CONNECTED_BIT);
		break;
	default:
		break;
    }
    return ESP_OK;
}

2、ダウンロードテスト

ESP-IDFコマンドプロンプトを開く

このプロジェクトディレクトリに入るcdコマンド

cd F:\ESP32_DevBoard_File\18_WIFI_AP_UDP

コンピューターのデバイスマネージャーで開発ボードのシリアルポート番号を表示する

idf.py -p COM9フラッシュモニターを実行してシリアルポート9からダウンロードして実行し、ポートを開いてデバイスのデバッグ情報を表示しますCtrl + cで終了します

テストプロセス

コードをダウンロードした後、コンピューターは "HelloBug" WIFIが表示されるのを待ち、それに接続します。パスワードは12345678です(コードで変更できます)。

接続が成功したら、コンピューター側でネットワークデバッグアシスタントを開きます。

接続方法を「UDP」に選択 

ローカルホストアドレス:192.168.4.2(開発ボードの印刷情報/コンピューターのローカル接続ステータスにあります)

ローカルホストポート:1257(何気なく9527にすることはできません。開発ボードのポートは9527です)

接続をクリックします

リモートホスト入力192.168.4.1:9527または255.255.255.255:9527

データを送信すると、開発ボードは同じデータを返します。詳細については、シリアルポート情報を確認してください。

テスト結果は次のとおりです。

おすすめ

転載: blog.csdn.net/cnicfhnui/article/details/108590638