Serve HTML from SPIFFS

PeterR
Posts: 621
Joined: Mon Jun 04, 2018 2:47 pm

Re: Serve HTML from SPIFFS

Postby PeterR » Tue Dec 18, 2018 6:44 pm

but my problem is that I have to store js and css file in flash. and it will take upto 350Kb of space to store it.
I am sure that you have already minified. After that you must 'suck it in' and use an ESP FLASH option or SD card.
Actually the ESP flash options are quite cheap. You buy the package fully wired as well! You need to be a little carefull if you have a heavy pin use count(1.8V, allocations of pins etc).
Remember that a webserver does not need heavy static file throughput so single/dual SPI should be fine.
Thin client is a pig on storage but you gain on interoperability & save on display costs.
You're other options may be to ditch JQuery (128K) and rethink your AJAX/property access. I mostly use Jquery out of convinience & because I have 16MB. Got sticky when I only had 256KB total many years back.
So you may be able to trade dev hours for $ UPC.
Good luck
EDIT: PS, I would not use SD for web - its more expensive than ESP flash. The other things is that if you lost power during update then the web would be down. You could dig into SD raw/sector details but ESP ROM integrates perfectly with OTA (& SD integrate with the often maligned FATFS). I saw comment from ESP guys that ESP FAT might be journeled but that was an equivocal comment.
EDIT++: But remember that you can only update ESP FLASH from a function in IRAM. That's gonna be hard if you use much of the IDF & especially BLE. Suppose that you could just keep your memcpy() in IRAM but you would not be seemlessly in an operational mode with background update if you use much of the IDF.
Its sounding a harder call then I made out....
& I also believe that IDF CAN should be fixed.

mikemoy
Posts: 604
Joined: Fri Jan 12, 2018 9:10 pm

Re: Serve HTML from SPIFFS

Postby mikemoy » Tue Dec 18, 2018 8:46 pm

I am using file system to store html code of webserver. but in my code there are some css, js file references which are runs over internet. so if network dont have internet my webserver won't see properly like bootstrap.
I had the same issue. This is how I resolved it. Hopefully this may help someone.

First the references for bootstrap and jquery in my index.html file.

Code: Select all

    <link rel='stylesheet' href='bootstrap.min.css'>
    <script src='jquery-3.3.1.min.js'></script>
    <script src='bootstrap.min.js'></script>
Next, make a new folder inside of the main folder called WebsiteFiles (or whatever, just remember the name you'll need it later), and put all your site files in there. Then you need to add "your" html files in your "component.mk" file like this.

Code: Select all

#
# "main" pseudo-component makefile.
#
# (Uses default behavior of compiling all source files in directory, adding 'include' to include path.)

COMPONENT_SRCDIRS += . WebsiteFiles ..
COMPONENT_EMBED_FILES := WebsiteFiles/index.html WebsiteFiles/bootstrap.min.css WebsiteFiles/bootstrap.min.js WebsiteFiles/favicon.ico WebsiteFiles/jquery-3.3.1.min.js WebsiteFiles/on.png WebsiteFiles/off.png
NOTE: these are my files, change them for yours.

I should note there that depending on your environment, when you make a change to the files in this folder you may need to do a clean and rebuild for the compiler to grab the change.

Ok, onto the servers end of things.

I created a file called WebServer.c. Some things to note here. Make sure your site files names are matched there at the top. "_binary_" must always be the first part of the name, followed by your filename, then "_start" and "_end".

So, when my ESP32 fires up and after networking gets going I call start_webserver(), and that's it to get the ball rolling.

This file was the development stage, meaning worked fine, but left allot of info printing and other things needed some cleaning.
Also, I am NOT saying this is the only or best way to skin this cat, so don't nit pick it ;)

Code: Select all

#include "Header.h"

/*
 *
 * If adding or changing and site files, make sure they added or removed from component.mk file. 
 * Also, if changes are made you need to clean then rebuild for it to compile those new files.
 * It does not do it automaitcally. 
 *
 **/


extern const uint8_t index_html_start[] asm("_binary_index_html_start");
extern const uint8_t index_html_end[]   asm("_binary_index_html_end");

extern const uint8_t bootstrap_min_css_start[] asm("_binary_bootstrap_min_css_start");
extern const uint8_t bootstrap_min_css_end[]   asm("_binary_bootstrap_min_css_end");

extern const uint8_t bootstrap_min_js_start[] asm("_binary_bootstrap_min_js_start");
extern const uint8_t bootstrap_min_js_end[]   asm("_binary_bootstrap_min_js_end");

extern const uint8_t favicon_ico_start[] asm("_binary_favicon_ico_start");
extern const uint8_t favicon_ico_end[]   asm("_binary_favicon_ico_end");

extern const uint8_t jquery_3_3_1_min_js_start[] asm("_binary_jquery_3_3_1_min_js_start");
extern const uint8_t jquery_3_3_1_min_js_end[]   asm("_binary_jquery_3_3_1_min_js_end");

extern const uint8_t on_switch_start[] asm("_binary_on_png_start");
extern const uint8_t on_switch_end[]   asm("_binary_on_png_end");

extern const uint8_t off_switch_start[] asm("_binary_off_png_start");
extern const uint8_t off_switch_end[]   asm("_binary_off_png_end");



/* An HTTP GET handler */
esp_err_t index_html_handler(httpd_req_t *req)
{
    printf("Main Page Requested\r\n");

    httpd_resp_set_type(req,"text/html");

    httpd_resp_send(req, (const char *)index_html_start, (index_html_end-1) - index_html_start);


    return ESP_OK;
}
/* An HTTP GET handler */
esp_err_t favicon_ico_handler(httpd_req_t *req)
{
	printf("favicon_ico_handler Page Requested\r\n");
    
	httpd_resp_set_type(req, "image/x-icon");

	httpd_resp_send(req, (const char *)favicon_ico_start, (favicon_ico_end-1) - favicon_ico_start);

	return ESP_OK;
}
/* An HTTP GET handler */
esp_err_t bootstrapMinCss_handler(httpd_req_t *req)
{
	printf("!!! Sending bootstrapMinCss !!!\r\n");

	httpd_resp_set_type(req, "text/css");

	httpd_resp_send(req, (const char *)bootstrap_min_css_start, (bootstrap_min_css_end-1) - bootstrap_min_css_start);


	return ESP_OK;
}
/* An HTTP GET handler */
esp_err_t bootstrapMinJS_handler(httpd_req_t *req)
{
	printf("!!! Sending bootstrapMinJs !!!\r\n");

	httpd_resp_set_type(req, "application/javascript");

	httpd_resp_send(req, (const char *)bootstrap_min_js_start, (bootstrap_min_js_end-1) - bootstrap_min_js_start);


	return ESP_OK;
}
/* An HTTP GET handler */
esp_err_t jquery_3_3_1_min_js_handler(httpd_req_t *req)
{
	printf("!!! Sending Requested jqueryMinJs !!!\r\n");

	httpd_resp_set_type(req, "application/javascript");

	httpd_resp_send(req, (const char *)jquery_3_3_1_min_js_start, (jquery_3_3_1_min_js_end-1) - jquery_3_3_1_min_js_start);


	return ESP_OK;
}
/* An HTTP GET handler */
esp_err_t on_png_handler(httpd_req_t *req)
{
	printf("!!! Sending on.png !!!\r\n");

	httpd_resp_set_type(req, "image/png");

	httpd_resp_send(req, (const char *)on_switch_start, (on_switch_end-1) - on_switch_start);

	return ESP_OK;
}
/* An HTTP GET handler */
esp_err_t off_png_handler(httpd_req_t *req)
{
	printf("!!! Sending off.png !!!\r\n");

	httpd_resp_set_type(req, "image/png");

	httpd_resp_send(req, (const char *) off_switch_start, (off_switch_end-1) - off_switch_start);

	return ESP_OK;
}




/* An HTTP POST handler */
esp_err_t echo_post_handler(httpd_req_t *req)
{
    char buf[100];
    char ledJSON[100];
    int ret, remaining = req->content_len;

    printf("Post Page Requested\r\n");
    memset(buf,0,sizeof(buf)-1);

//    while (remaining > 0) 
    {
        /* Read the data for the request */
        if ((ret = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)))) < 0) 
        {
            return ESP_FAIL;
        }

        /* Log data received */
	    ESP_LOGI("WEBSEREVER", "=========== RECEIVED DATA ==========");
	    ESP_LOGI("WEBSEREVER", "%.*s", ret, buf);
	    ESP_LOGI("WEBSEREVER", "====================================");


        if(strcmp(buf,"runtime=")==0)
        {
            printf("Runtime Request\r\n");
	        sprintf(ledJSON, "{\"timestat\":{\"hours\":%u,\"minutes\":%u,\"seconds\":%u}}", hours, minutes, seconds);
            httpd_resp_set_type(req,"application/json");

            httpd_resp_send(req, ledJSON, strlen(ledJSON));

        }
        else if(strcmp(buf,"getpower")==0)
        {
            printf("Get Power Request\r\n");
            sprintf(ledJSON, "{\"powerstate\":\"%u\"}", 1);
            httpd_resp_set_type(req,"application/json");

            httpd_resp_send(req, ledJSON, strlen(ledJSON));

        }
        else if(strcmp(buf,"setpower=0")==0)
        {
            printf("setpower=0 Request\r\n");
            sprintf(ledJSON, "{\"powerstate\":\"%u\"}", 1);
            httpd_resp_set_type(req,"text/plain");

            httpd_resp_send(req, ledJSON, strlen(ledJSON));

        }
        else if(strcmp(buf,"setpower=1")==0)
        {
            printf("setpower=1 Request\r\n");
            sprintf(ledJSON, "ok");
            httpd_resp_set_type(req,"text/plain");

            httpd_resp_send(req, ledJSON, strlen(ledJSON));

        }

        else
        {
            printf("!!! ELSE Could Not Find IT !!!\r\n");
            /* Send back the same data */
            // End response
           httpd_resp_send_404(req);
        }

        remaining -= ret;

    }

    return ESP_OK;
}
httpd_uri_t index_html = {
    .uri       = "/",
    .method    = HTTP_GET,
    .handler   = index_html_handler,
    /* Let's pass response string in user
     * context to demonstrate it's usage */
    .user_ctx  = NULL
};
httpd_uri_t bootstrapMinCss = {
	.uri = "/bootstrap.min.css",
	.method = HTTP_GET,
	.handler = bootstrapMinCss_handler,
	/* Let's pass response string in user
	 * context to demonstrate it's usage */
	.user_ctx = NULL
};
httpd_uri_t bootstrapMinJs = {
	.uri = "/bootstrap.min.js",
	.method = HTTP_GET,
	.handler = bootstrapMinJS_handler,
	/* Let's pass response string in user
	 * context to demonstrate it's usage */
	.user_ctx = NULL
};
httpd_uri_t jquery_3_3_1_min_js = {
	.uri = "/jquery-3.3.1.min.js",
	.method = HTTP_GET,
	.handler = jquery_3_3_1_min_js_handler,
	/* Let's pass response string in user
	 * context to demonstrate it's usage */
	.user_ctx = NULL
};
httpd_uri_t on_png = {
	.uri = "/on.png",
	.method = HTTP_GET,
	.handler = on_png_handler,
	/* Let's pass response string in user
	 * context to demonstrate it's usage */
	.user_ctx = NULL
};
httpd_uri_t off_png = {
	.uri = "/off.png",
	.method = HTTP_GET,
	.handler = off_png_handler,
	/* Let's pass response string in user
	 * context to demonstrate it's usage */
	.user_ctx = NULL
};
httpd_uri_t favicon_ico = {
    .uri       = "/favicon.ico",
    .method    = HTTP_GET,
    .handler   = favicon_ico_handler,
    /* Let's pass response string in user
     * context to demonstrate it's usage */
    .user_ctx  = NULL
};
httpd_uri_t echo = {
    .uri       = "/rgb",
    .method    = HTTP_POST,
    .handler   = echo_post_handler,
    .user_ctx  = NULL
};

httpd_handle_t start_webserver(void)
{
    httpd_handle_t server = NULL;
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();

    // Start the httpd server
    ESP_LOGI("WEBSEREVER", "Starting server on port: '%d'", config.server_port);
    if (httpd_start(&server, &config) == ESP_OK) 
    {
        // Set URI handlers
        ESP_LOGI("WEBSEREVER", "Registering URI handlers");

        httpd_register_uri_handler(server, &index_html);
	    httpd_register_uri_handler(server, &favicon_ico);
	    httpd_register_uri_handler(server, &bootstrapMinCss);
	    httpd_register_uri_handler(server, &bootstrapMinJs);
	    httpd_register_uri_handler(server, &jquery_3_3_1_min_js);
	    httpd_register_uri_handler(server, &on_png);
	    httpd_register_uri_handler(server, &off_png);
        httpd_register_uri_handler(server, &echo);

        return server;
    }

	ESP_LOGI("WEBSEREVER", "Error starting server!");
    return NULL;
}

void stop_webserver(httpd_handle_t server)
{
    // Stop the httpd server
    httpd_stop(server);
}




Who is online

Users browsing this forum: No registered users and 135 guests