webserver using FATFS file system

burkulesomesh43
Posts: 132
Joined: Tue Aug 14, 2018 6:21 am
Location: India

webserver using FATFS file system

Postby burkulesomesh43 » Wed Dec 12, 2018 1:31 pm

Hi all,
I want to store a html file in flash and use that file for webserver.
I just want to hit whole html file not like reading it and use that variable in netconn_write(); function to hit that page.
please the the code as follows. is there any api to hit that file directly from flash?

Code: Select all


#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include "freertos/portmacro.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "tcpip_adapter.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "esp_vfs.h"
#include "esp_vfs_fat.h"


static EventGroupHandle_t wifi_event_group;
const int CONNECTED_BIT = BIT0;
static char* TAG = "webserver-file";

#include "lwip/err.h"
#include "string.h"

// Handle of the wear levelling library instance
static wl_handle_t s_wl_handle = WL_INVALID_HANDLE;

// Mount path for the partition
const char *base_path = "/spiflash";

const static char http_html_hdr[] =
    "HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n";
const static char http_index_hml[] ="<!DOCTYPE html>"
		"<html>"
		"<body>"
		"<form action=\"/action_page.php\">"
		"Select a file: <input type=\"file\" name=\"myFile\"><br><br>"
		"<input type=\"submit\">"
		"</form>"
		"</body>"
		"</html>";

#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/api.h"

static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    switch(event->event_id) {
    case SYSTEM_EVENT_STA_START:
        esp_wifi_connect();
        break;
    case SYSTEM_EVENT_STA_GOT_IP:
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
        printf("got ip\n");
        printf("ip: " IPSTR "\n", IP2STR(&event->event_info.got_ip.ip_info.ip));
        printf("netmask: " IPSTR "\n", IP2STR(&event->event_info.got_ip.ip_info.netmask));
        printf("gw: " IPSTR "\n", IP2STR(&event->event_info.got_ip.ip_info.gw));
        printf("\n");
        fflush(stdout);
        break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
        /* This is a workaround as ESP32 WiFi libs don't currently
           auto-reassociate. */
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
        break;
    default:
        break;
    }
    return ESP_OK;
}

static void initialise_wifi(void)
{
    tcpip_adapter_init();
    wifi_event_group = xEventGroupCreate();
    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) );
    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    wifi_config_t sta_config = {
        .sta = {
            .ssid = "niruha",
            .password = "1234567890",
            .bssid_set = false
        }
    };

    ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config) );
    ESP_ERROR_CHECK( esp_wifi_start() );
}

static void
http_server_netconn_serve(struct netconn *conn)
{
  struct netbuf *inbuf;
  char *buf;
  u16_t buflen;
  err_t err;

  /* Read the data from the port, blocking if nothing yet there.
   We assume the request (the part we care about) is in one netbuf */
  err = netconn_recv(conn, &inbuf);

  if (err == ERR_OK) {
    netbuf_data(inbuf, (void**)&buf, &buflen);

    // strncpy(_mBuffer, buf, buflen);

    /* Is this an HTTP GET command? (only check the first 5 chars, since
    there are other formats for GET, and we're keeping it very simple )*/
    printf("buffer = %s \n", buf);
    if (buflen>=5 &&
        buf[0]=='G' &&
        buf[1]=='E' &&
        buf[2]=='T' &&
        buf[3]==' ' &&
        buf[4]=='/' ) {
          printf("buf[5] = %c\n", buf[5]);
      /* Send the HTML header
             * subtract 1 from the size, since we dont send the \0 in the string
             * NETCONN_NOCOPY: our data is const static, so no need to copy it
       */

      // Open file for reading
             ESP_LOGI(TAG, "Reading file");
             FILE* f = fopen("/spiflash/hello.txt", "rb");
             if (f == NULL) {
                 ESP_LOGE(TAG, "Failed to open file for reading");
                 return;
             }
             char line[500];
             fgets(line, sizeof(line), f);
             fclose(f);
             // strip newline
             char *pos = strchr(line, '\n');
             if (pos) {
                 *pos = '\0';
             }
             ESP_LOGI(TAG, "Read from file: '%s'", line);

      netconn_write(conn, http_html_hdr, sizeof(http_html_hdr)-1, NETCONN_NOCOPY); // Open renamed file for reading
      netconn_write(conn, line, strlen(line)-1, NETCONN_NOCOPY);
    }

  }
  /* Close the connection (server closes in HTTP) */
  netconn_close(conn);

  /* Delete the buffer (netconn_recv gives us ownership,
   so we have to make sure to deallocate the buffer) */
  netbuf_delete(inbuf);
}

static void http_server(void *pvParameters)
{
  struct netconn *conn, *newconn;
  err_t err;
  conn = netconn_new(NETCONN_TCP);
  netconn_bind(conn, NULL, 80);
  netconn_listen(conn);
  do {
     err = netconn_accept(conn, &newconn);
     if (err == ERR_OK) {
       http_server_netconn_serve(newconn);
       netconn_delete(newconn);
     }
   } while(err == ERR_OK);
   netconn_close(conn);
   netconn_delete(conn);
}

int app_main(void)
{
    nvs_flash_init();
    ESP_LOGI(TAG, "Mounting FAT filesystem");
        // To mount device we need name of device partition, define base_path
        // and allow format partition in case if it is new one and was not formated before
        const esp_vfs_fat_mount_config_t mount_config = {
                .max_files = 4,
                .format_if_mount_failed = true,
                .allocation_unit_size = CONFIG_WL_SECTOR_SIZE
        };
        esp_err_t err = esp_vfs_fat_spiflash_mount(base_path, "storage", &mount_config, &s_wl_handle);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
            return;
        }
        ESP_LOGI(TAG, "Opening file");
        FILE *f = fopen("/spiflash/hello.txt", "wb");
        if (f == NULL) {
            ESP_LOGE(TAG, "Failed to open file for writing");
            return;
        }
        fprintf(f, "%s\n",http_index_hml);
        fclose(f);
        ESP_LOGI(TAG, "File written");

    initialise_wifi();

    xTaskCreate(&http_server, "http_server", 1024*4, NULL, 5, NULL);
    return 0;
}
Last edited by burkulesomesh43 on Mon Dec 17, 2018 8:21 am, edited 2 times in total.
--
Somesh Burkule

User avatar
brp80000
Posts: 138
Joined: Thu Oct 04, 2018 7:13 pm

Re: webserver using FATFS file system

Postby brp80000 » Wed Dec 12, 2018 5:33 pm

I am use part of code for the same (fatfs to webserver) from this GIT
https://github.com/limiter121/esp32-obd2-emulator

burkulesomesh43
Posts: 132
Joined: Tue Aug 14, 2018 6:21 am
Location: India

Re: webserver using FATFS file system

Postby burkulesomesh43 » Thu Dec 13, 2018 4:49 am

brp80000 wrote:
Wed Dec 12, 2018 5:33 pm
I am use part of code for the same (fatfs to webserver) from this GIT
https://github.com/limiter121/esp32-obd2-emulator
It gives an error. there is no header in esp idf.

C:/esp-idf-v3.1.1/examples/somesh/webserver-file/main/main.c:26:25: fatal error: http_server.h: No such file or directory
compilation terminated.
--
Somesh Burkule

ESP_Anurag
Posts: 19
Joined: Fri Aug 31, 2018 5:37 am

Re: webserver using FATFS file system

Postby ESP_Anurag » Thu Dec 13, 2018 6:18 am

ESP-IDF has it's own native http server now (see esp_http_server). Check this answer, from a previous post, about serving files off a FAT formatted SD card : viewtopic.php?p=29992#p29992

burkulesomesh43
Posts: 132
Joined: Tue Aug 14, 2018 6:21 am
Location: India

Re: webserver using FATFS file system

Postby burkulesomesh43 » Thu Dec 13, 2018 6:59 am

ESP_Anurag wrote:
Thu Dec 13, 2018 6:18 am
ESP-IDF has it's own native http server now (see esp_http_server). Check this answer, from a previous post, about serving files off a FAT formatted SD card : viewtopic.php?p=29992#p29992
I am using esp-idf v3.1.1 which does not have esp_http_server.
--
Somesh Burkule

burkulesomesh43
Posts: 132
Joined: Tue Aug 14, 2018 6:21 am
Location: India

Re: webserver using FATFS file system

Postby burkulesomesh43 » Thu Dec 13, 2018 7:30 am

can i use the files like used in following link.
http://zerothelement21.blogspot.com/201 ... f-sdk.html

but i dont know then where this file is stored. in EEPROM or in code.
--
Somesh Burkule

ESP_Anurag
Posts: 19
Joined: Fri Aug 31, 2018 5:37 am

Re: webserver using FATFS file system

Postby ESP_Anurag » Thu Dec 13, 2018 9:04 am

can i use the files like used in following link.
http://zerothelement21.blogspot.com/201 ... f-sdk.html
Yes you can. As described in the link, you simply need to put the following in your component.mk

Code: Select all

COMPONENT_EMBED_FILES := index.html
And use the following two pointers in your code to track the start and end of the file

Code: Select all

extern const uint8_t index_html_start[] asm("_binary_index_html_start");
extern const uint8_t index_html_end[] asm("_binary_index_html_end");
but i dont know then where this file is stored. in EEPROM or in code.
It's stored in flash, and is very simple to access using the two pointers. You just need to write a URI handler function like this:

Code: Select all

esp_err_t index_html_get_handler(httpd_req_t *req)
{
    extern const uint8_t index_html_start[] asm("_binary_index_html_start");
    extern const uint8_t index_html_end[] asm("_binary_index_html_end");

    httpd_resp_send(req, (const char*)index_html_start, (index_html_end - index_html_start));
    return ESP_OK;
}
And inside your main function start the server and register the URI handler:

Code: Select all

    httpd_handle_t server = NULL;
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();

    httpd_uri_t index_html = {
        .uri       = "/",
        .method    = HTTP_GET,
        .handler   = index_html_get_handler,
        .user_ctx  = NULL
    };

    httpd_start(&server, &config);
    httpd_register_uri_handler(server, &index_html);
All httpd_ APIs are available from esp_http_server.h

jcsbanks
Posts: 305
Joined: Tue Mar 28, 2017 8:03 pm

Re: webserver using FATFS file system

Postby jcsbanks » Thu Dec 13, 2018 11:41 pm

Code: Select all

W (14605) httpd_parse: parse_block: response uri/header too big
W (14605) httpd_txrx: httpd_resp_send_err: 431 Request Header Fields Too Large - Header fields are too long for server to interpret
W (14615) httpd_parse: parse_block: incomplete (1/21) with parser error = 16
W (14625) httpd_txrx: httpd_resp_send_err: 400 Bad Request - Server unable to understand request due to invalid syntax
W (14635) httpd_parse: parse_block: incomplete (0/31) with parser error = 16
When using the modifications suggested above to http_server/simple and trying an http POST, I get the above errors.

The POST is:

Code: Select all

POST http://192.168.1.113/ HTTP/1.1
Host: 192.168.1.113
Connection: keep-alive
Content-Length: 31
Cache-Control: max-age=0
Origin: http://192.168.1.113
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://192.168.1.113/
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8

firstname=Mickey&lastname=Mouse
Increasing

Code: Select all

#define PARSER_BLOCK_SIZE  128
in esp_httpd_priv.h makes no difference.

Trying to track down the source of the error.

jcsbanks
Posts: 305
Joined: Tue Mar 28, 2017 8:03 pm

Re: webserver using FATFS file system

Postby jcsbanks » Fri Dec 14, 2018 12:18 am

CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
CONFIG_HTTPD_MAX_URI_LEN=1024

In sdkconfig (original values 512) fixes it.

The content length from Chrome for a short POST was 548 bytes.

ESP_Anurag
Posts: 19
Joined: Fri Aug 31, 2018 5:37 am

Re: webserver using FATFS file system

Postby ESP_Anurag » Mon Dec 17, 2018 6:33 am

You can have a sdkconfig.defaults in your project folder with the config value overrides, or use `make menuconfig` to override these values

Who is online

Users browsing this forum: letter57 and 211 guests