EnsekiTT Blog

EnsekiTTが書くブログです。

ESP-WROOM-32を使ってWiFi経由でGETリクエストした話。

つまりなにしたの?

ESP-WROOM-32でLED-PWMできるようになったので、今度はWiFiからGETリクエスト飛ばしてみた。
f:id:ensekitt:20170907001322j:plain

前回(LED-PWM)

ensekitt.hatenablog.com

ESP-WROOM-32の環境構築

ensekitt.hatenablog.com

用意したもの

ブレッドボード(ESP-WROOM32にはちょっと狭い)
ESP-WROOM32
いつも使っている無線LANルータ

コードの概要

Kconfig.projbuild

WiFiを繋ぐためにはSSIDとパスワードが必要なので、Kconfig.projbuildでビルド時にSSIDとパスワードを指定するようにした。

menu "Config"

config WIFI_SSID
    string "WiFi SSID"
    default "myssid"
    help
	SSID (network name) for the example to connect to.

config WIFI_PASSWORD
    string "WiFi Password"
    default "mypassword"
    help
	WiFi password (WPA or WPA2) for the example to use.

endmenu

これでとりあえず初回起動時にWiFiSSIDとPasswordをプロンプトが訪ねてくる。

WiFiの準備

  • TCP/IPアダプタの初期化
  • イベントハンドラの準備
  • WiFiコンフィグ関連の準備
  • WiFiドライバの起動
  • WiFi接続
  • Webへのアクセスタスクの実行
  • アクセスタスクの削除
  • 接続解除
  • WiFiドライバの停止
void app_main()
{
  ESP_ERROR_CHECK( nvs_flash_init() );
  ESP_LOGI(TAG, "WAKE UP!");

  //TCP/IPアダプタの初期化
  tcpip_adapter_init();

  //イベントハンドラの準備
  wifi_event_group = xEventGroupCreate();
  ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));

  //WiFiコンフィグ関連の準備
  wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  ESP_ERROR_CHECK(esp_wifi_init(&cfg));
  wifi_config_t wifi_config = {
    .sta = {
      .ssid = DEFAULT_SSID,
	    .password = DEFAULT_PWD
    },
  };
  ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
  ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));

  //WiFiドライバの起動
  ESP_LOGI(TAG, "WIFI_START");
  ESP_ERROR_CHECK(esp_wifi_start());
  vTaskDelay(1000 / portTICK_PERIOD_MS);

  //WiFi接続
  ESP_LOGI(TAG, "WIFI_CONNECT");
  ESP_ERROR_CHECK(esp_wifi_connect());

  //Webへアクセスタスクの実行
  xTaskHandle xHandle;
  xTaskCreate(&http_get_task, "http_get_task", 4096, NULL, 5, &xHandle);
  vTaskDelay(30000 / portTICK_PERIOD_MS);

  //アクセスタスクの削除
  vTaskDelete( xHandle );

  //接続解除
  ESP_LOGI(TAG, "DISCONNECT");
  ESP_ERROR_CHECK(esp_wifi_disconnect());
  vTaskDelay(1000 / portTICK_PERIOD_MS);

  //WiFiドライバの停止
  ESP_LOGI(TAG, "STOP");
  ESP_ERROR_CHECK(esp_wifi_stop());
}

Webへのアクセスタスク

  • 接続済BITの確認
  • 接続先IPの確認
  • ソケット作成
  • サーバへ接続
  • リクエスト実行
  • レスポンスの表示
static void http_get_task(void *pvParameters)
{
    const struct addrinfo hints = {
        .ai_family = AF_INET,
        .ai_socktype = SOCK_STREAM,
    };
    struct addrinfo *res;
    struct in_addr *addr;
    int s, r;
    char recv_buf[64];

    while(1) {
        //接続済BITの確認
        xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
                            false, true, portMAX_DELAY);
        ESP_LOGI(TAG, "Connected to AP");

        int err = getaddrinfo(WEB_SERVER, "80", &hints, &res);

        if(err != 0 || res == NULL) {
            ESP_LOGE(TAG, "DNS lookup failed err=%d res=%p", err, res);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            continue;
        }

        //接続先IPの確認
        addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
        ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", inet_ntoa(*addr));

        //ソケット作成
        s = socket(res->ai_family, res->ai_socktype, 0);
        if(s < 0) {
            ESP_LOGE(TAG, "... Failed to allocate socket.");
            freeaddrinfo(res);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            continue;
        }
        ESP_LOGI(TAG, "... allocated socket\r\n");

        //サーバへ接続
        if(connect(s, res->ai_addr, res->ai_addrlen) != 0) {
            ESP_LOGE(TAG, "... socket connect failed errno=%d", errno);
            close(s);
            freeaddrinfo(res);
            vTaskDelay(4000 / portTICK_PERIOD_MS);
            continue;
        }
        ESP_LOGI(TAG, "... connected");
        freeaddrinfo(res);
        
        //リクエスト実行
        if (write(s, REQUEST, strlen(REQUEST)) < 0) {
            ESP_LOGE(TAG, "... socket send failed");
            close(s);
            vTaskDelay(4000 / portTICK_PERIOD_MS);
            continue;
        }
        ESP_LOGI(TAG, "... socket send success");

        //レスポンスの表示
        do {
            bzero(recv_buf, sizeof(recv_buf));
            r = read(s, recv_buf, sizeof(recv_buf)-1);
            for(int i = 0; i < r; i++) {
                putchar(recv_buf[i]);
            }
        } while(r > 0);

        ESP_LOGI(TAG, "... done reading from socket. Last read return=%d errno=%d\r\n", r, errno);
        close(s);
        ESP_LOGI(TAG, "Success!");
        for(int countdown = 10; countdown >= 0; countdown--) {
          ESP_LOGI(TAG, "%d... ", countdown);
          vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
        ESP_LOGI(TAG, "Starting again!");
    }
}

書いたコード

github.com

僕のブログにGETリクエストできました!

cd esp_trial/pwm
make menuconfig

で接続先の設定を行って

make flash monitor

で実行する。

つらつらとブログのHTMLが流れた。

今日はここまで!

APIを叩けるようになればだいぶ世界が広がりそう。