ESP32 Урок 27. Wi-Fi. STA. Простой HTTP Server



Продолжаем работу с протоколами модели OSI и на данном уроке мы попытаемся создать простой сервер HTTP, который позволит нам принять запрос документа от клиента, обработать его и в ответ направить клиенту нужную информацию. Также мы раньше подобные задачи решали с использованием других контроллеров, в том числе и родственного ESP8266, поэтому думаю, что с данной задачей мы без особого труда справимся. Сервер считается простым, так как отвечать он будет на запросы не любых документов, а только главной страницы и иконки приложения. Также мы для упрощения задачи не используем шифрование.

Дисплей нам на данном уроке не потребуется, поэтому схема наша будет состоять только из отладочной платы с контроллером ESP32, подключенной к USB-порту компьютера

 

 

Проект за основу мы возьмём из прошлого урока с именем WIFI_STA_TCP_SERVER и присвоим ему имя WIFI_STA_HTTP_SERVER.

Откроем проект в Espressif IDE и удалим файлы lcd2004.hlcd2004.ci2c_user.h и i2c_user.c, так как с дисплеем мы работать не будем. Также подключение данных модулей мы удалим и в файле CMakeLists.txt

 

set(COMPONENT_SRCS "main.c wifi.c tcp.c i2c_user.c lcd2004.c")

 

В файле Kconfig.projbuild удалим секции, отвечающие за ножки I2C

 

config SDA_GPIO
  int "SDA GPIO number"
  range 0 48
  default 21
  help
  GPIO number SDA.

config SCL_GPIO
  int "SCL GPIO number"
  range 0 48
  default 22
  help
  GPIO number SCL.

 

Зайдём в конфигуратор и изменим порт на значение по умолчанию для работы с протоколом HTTP

 

 

Удалим подключение заголовочного файла из main.h и tcp.h

 

#include "lcd2004.h"

 

В функции app_main файла main.c удалим строки связанные с инициализацией дисплея

 

ret = i2c_ini();
ESP_LOGI(TAG, "i2c_ini: %d", ret);
LCD_ini();

 

Файлы tcp.h и tcp.c переименуем соответственно в http.h и http.c.

Изменим подключение модуля также в файле CMakeLists.txt

 

set(COMPONENT_SRCS "main.c wifi.c http.c")

 

Перейдём в файл http.c и удалим функцию vLCDTask вместе с телом.

Удалим также и функцию client_socket_task.

Структуры и очереди нам также не потребуются

 

typedef struct struct_client_socket_t {
  struct sockaddr_in cliaddr;
  socklen_t sockaddrsize;
  int accept_sock;
  uint16_t y_pos;
} struct_client_socket;
struct_client_socket client_socket01;
//-------------------------------------------------------------
typedef struct
{
  unsigned char y_pos;
  unsigned char x_pos;
  char *str;
} qLCDData;
//------------------------------------------------
xQueueHandle lcd_string_queue = NULL, xQueueClose = NULL, xQueueCloseAsk = NULL;

 

Переименуем строку

 

static const char *TAG = "http";

 

 

Также переименуем функцию задачи

 

void http_task(void *pvParameters)

 

Не забываем также о прототипе в заголовочном файле. Также в функции app_main файла main.c переименуем аргументы в создании задачи

 

xTaskCreate(http_task, «http_task«, 4096, NULL, 5, NULL);

 

Вернёмся в файл http.c и в функции http_task удалим объявление хендла задачи дисплея

 

TaskHandle_t xLCDTaskHandle = NULL;

 

Удалим инициализацию позиции

 

  unsigned char y_pos = 0;

 

Удалим также вот эти строки

 

qLCDData xLCDData;
char str1[21];
xLCDData.y_pos = 1;
xLCDData.str = str1;

 

Удалим и вот эти строки, также связанные с дисплеем

 

lcd_string_queue = xQueueCreate(10, sizeof(qLCDData));
xQueueClose = xQueueCreate(10, sizeof(unsigned char));
xQueueCloseAsk = xQueueCreate(10, sizeof(unsigned char));
xTaskCreate(vLCDTask, «vLCDTask», 2048, NULL, 2, &xLCDTaskHandle);

 

Здесь удалим перевод строки, чтобы не создавалась лишняя, в функции для вывода логов строки переводятся автоматически

 

ESP_LOGI(TAG, «Create socket…\n«);

ESP_LOGE(TAG, «socket not created\n«);

 

Тут исправим грамматическую ошибочку

 

//Свяжем сокет с адресом сервера

 

В следующем условии удалим уничтожение задачи и очереди

 

vQueueDelete(lcd_string_queue);
vTaskDelete(NULL);

 

Тело следующего условия удалим полностью

 

if(accept_sock >= 0)
{
  client_socket01.accept_sock = accept_sock;
  client_socket01.cliaddr = cliaddr;
  client_socket01.sockaddrsize = sockaddrsize;
  client_socket01.y_pos = y_pos%4;
  xTaskCreate(client_socket_task, "client_socket_task", 4096, (void*)&client_socket01, 5, NULL);
  y_pos++;
}

 

В конце тела функции удалим вот эти строки

 

sprintf(str1, "Disonnected");
xQueueSendToBack(lcd_string_queue, &xLCDData, 0);
vTaskDelay(2000 / portTICK_RATE_MS);
vTaskDelete(xLCDTaskHandle);
vQueueDelete(lcd_string_queue);

 

Теперь у нас хотя бы будет собираться код.

Добавим переменную в объявление

 

int sockfd, accept_sock, ret;

 

Объявим указатель на буфер, а также объявим и инициализируем длину буфера

 

 

В условии, тело которого мы удалили, запросим память для буфера и попытаемся принять от клиента пакет

 

 

Теперь нам надо будет подготовить документы, которые мы будем предоставлять клиенту на его запросы.

 

 

Сделаем мы это так, как делали раньше с AVR, подготовив массив с помощью утилиты makefsdata (в конце страницы будет ссылка на архив утилиты с примерами страницы и иконки). Содержимое страницы и заголовка HTTP мы поместим в глобальные массивы

 

 

С иконкой поступим немного по-другому. Мы её не будем собирать из двух массивов, а создадим для неё общий массив вместе с заголовком. Памяти лишней мы не истратим, так как иконка у нас одна. Зато передавать мы её будем сразу из исходного массива

 

 

Вернёмся в функцию http_task и поместим наш ответ на запрос главной страницы в буфер, соединив наши массивы заголовка и контента страницы, а перед этим отфильтровав всё ненужное

 

 

Отправим пакет клиенту

 

 

А если запрос был на иконку, то передадим наш массив сразу, ничего не копируя и не соединяя

 

 

Выйдем из условия наличия ненулевого пакета (посчитайте закрывающие скобки) и разъединимся с клиентом, а затем освободим память, данную нам под буфер

 

 

В принципе, это весь код нашего простенького сервера HTTP. Соберём проект, прошьём контроллер и в терминале запомним сетевой адрес нашего сервера (отладочной платы)

 

 

Попытаемся в браузере запросить страницу и, если всё нормально, то мы получим и страницу и иконку

 

 

В анализаторе трафика у нас тоже всё нормально. Все ответы пришли, порты после получения документов отключились

 

 

Итак, на данном уроке нам удалось создать простейший HTTP-сервер, который может обрабатывать запрос документов от клиента и передавать ему их в форме пакета HTTP.

Всем спасибо за внимание!

 

Данная статья в Дзен.

 

 

Предыдущий урок Программирование МК ESP32 Следующий урок

 

Исходный код

 

Утилита для получения двоичного кода страниц и других файлов: makefsdata

 

 

Недорогие отладочные платы ESP32 можно купить здесь:

На AliExpress Недорогие отладочные платы ESP32

На Яндекс.Маркет Недорогие отладочные платы ESP32

Логический анализатор 16 каналов можно приобрести (AliExpress) здесь

 

 

Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)

ESP32 Wi-Fi. STA. Простой HTTP Server

Смотреть ВИДЕОУРОК в Дзен (нажмите на картинку)

ESP32 Wi-Fi. STA. Простой HTTP Server

Один комментарий на “ESP32 Урок 27. Wi-Fi. STA. Простой HTTP Server
  1. Алексей:

    Сделайте проект пожалуйста где SD карта (с видео файлом) подключается к ESP32. А просмотреть этот файл можно было-бы на «допустим» планшетe.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*