Solution 1 :

Use SPIFFS filesystem

You can use the SPI flash on your ESP8266 as a filesystem to store the HTML and Javascript files. The SPIFFS component is used for this purpose ( https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#spiffs-and-littlefs ).

The Chart.js file is relatively large – approx. 180 kB even when minified – so this might only be feasible when using an ESP8266 board with at least 4 MB flash memory.

You don’t specify which ESP8266 platform you are using, but my NodeMCU variant has 4 MB Flash. I allocate a fraction of this – typically 1 MB – for the filesystem.

Preparing to use the SPIFFS filesystem with Arduino is a 3-step process:

  • Firstly download the SPIFFS upload tool from https://github.com/esp8266/arduino-esp8266fs-plugin (go to the ‘Releases’ page)
    • follow the instructions there to install it alongside your Arduino installation
  • Create a data sub-folder in your Sketch folder with your HTML and CSS files
    • /data –
      • /index.html
      • /Chart.min.js
  • Upload the filesystem contents using the Arduino IDE
    • Tools -> ESP8266 Sketch Data Upload

Once you’ve done that you can use the filesystem more-or-less in the following manner …

  #include "FS.h"

  // snip

  if (!SPIFFS.begin()) {
    Serial.println("Failed to mount filesystem!n");
  }

  File file = SPIFFS.open("/index.html", "r");

  file.close();

Particularly relevant to your application is the inclusion of an overloaded streamFile() method in the ESP8266WebServer class which accepts a File object as argument. Assuming you have

static ESP8266WebServer server(80);

somewhere in your code, you can use this method as follows …

static void handleRoot() {
  File file = SPIFFS.open("/index.html", "r");
  if (!file) {
    server.send(500, "text/plain", "Problem with filesystem!n");
    return;
  }
  server.streamFile(file, "text/html");
  file.close();
}

As you probably know already, the handleRoot() function is intended as a server callback – which should be installed using server.on("/", handleRoot);.

Map URIs in HTTP request to filesystem paths

Now for the most useful part …

You can use the server.onNotFound(); method to send arbitrary files to a web client. First of all create the relevant callback:

static void handleNotFound() {
  String path = server.uri(); // Important!
  if (!SPIFFS.exists(path)) {
    server.send(404, "text/plain", "Path " + path + " not found. Please double-check the URL");
    return;
  }
  String contentType = "text/plain";
  if (path.endsWith(".css")) {
    contentType = "text/css";
  }
  else if (path.endsWith(".html")) {
    contentType = "text/html";
  }
  else if (path.endsWith(".js")) {
    contentType = "application/javascript";
  }
  File file = SPIFFS.open(path, "r");
  server.streamFile(file, contentType);
  file.close();
}

Then install it in your setup() function:

server.onNotFound(handleNotFound);

HTML and CSS files

If you then update your index.html – changing

<script src="./node_modules/chart.js/dist/Chart.min.js"></script>

to simply

<script src="Chart.min.js"></script>

and upload the contents of your data folder using the method outlined above, your application should work as expected.

Screenshot of web page served by my own ESP8266 shown below.

Chart JS demo running on ESP8266 web server

Problem :

I have set up the esp8266 in access point mode so i can access a web server from it. I want to be able to see a chart on this page. Is there any way to use chart.js or similar in html code without needing a wifi connection?

this is my html string which I send to the server:

const PROGMEM char* s = R"foo(
<!DOCTYPE HTML>
<html>

<head>
    <meta charset="utf-8" />
    <title>Chart.js demo</title>
    <script src="./node_modules/chart.js/dist/Chart.min.js"></script>
</head>

<body>
    <h1>Chart.js Sample</h1>
    <div class="chart-container" style="width: 600px; height: 400px">
        <canvas id="countries"></canvas>
    </div>

    <script>
        var pieData = {
            datasets: [{
                data: [20, 40, 10, 30],
                backgroundColor: ["#878BB6", "#4ACAB4", "#FF8153", "#FFEA88"]
            }]
        };

        // Get the context of the canvas element we want to select
        var countries = document.getElementById("countries").getContext("2d");
        new Chart(countries, {
            type: 'pie',
            data: pieData
        });
    </script>
</body>

</html>
)foo";

Comments

Comment posted by randomnerdtutorials.com/…

You would need to serve the js in a second request or inline it, maybe you can follow this tutorial:

Comment posted by David Collins

I think the best approach here is to store your HTML and Javascript (and maybe CSS) on the SPIFFS. It is relatively straight forward to do this using Arduino.

Comment posted by Marion Boynton

Hi David 🙂 thanks so much for the response! i have tried to implement this but the chart still does not appear… 🙁 any chance you could post the code so i can see where i am going wrong? In handleroot function what did you pass for the html file as i previously had a progmem char but if i save a sepearte html file i am not sure how to pass it to the function?

Comment posted by pastebin.com/NmJdXNv5

@MarionBoynton: I have pasted my code at

Comment posted by David Collins

Using

Comment posted by Marion Boynton

Hi David. I had it working but as I have tried to edit the chart I have not managed to get it working again. The page loads but no chart appears. I think there is something wrong with my html file may how I am accessing chart.js? this is my code currently…

Comment posted by pastebin.com

@MarionBoynton: I can’t see your code – comments have a character limit of a few hundred characters. I suggest either pasting your updated code on

By

Leave a Reply

Your email address will not be published. Required fields are marked *