como-servir-y-consumir-un-api-rest-con-esp8266-axios-y-vuejs

How to Serve and Consume a REST API with ESP32, Axios and VueJs

  • 4 min

Axios and VueJS let us build a reactive frontend that consumes a REST API served from an ESP32 or ESP8266, separating the web interface from the device logic.

The idea is to combine two pieces that fit together very well: Axios to perform HTTP requests and VueJS to keep the interface in sync. The microcontroller acts as the backend, serving both the REST API and the web page executed in the browser.

With this we can build a web application that is much cleaner than a loose collection of buttons and ad hoc calls. Each part handles what it should handle, which helps keep the code from turning into a mess.

First of all, the backend in this example is the same one we used to serve a REST API with JSON. In other words, the code on the ESP32 does not need to change.

So as not to be tedious and make the post unnecessarily long, we will omit it. You have it in the previous examples of the series and in the code on Github.

What will change, of course, is the frontend that we are going to serve from the SPIFFS, which now becomes.

Where we see that the code of our page has been adorned with the tags typical of a VueJs App.

<!DOCTYPE html>
<html>
<head>
  <title>ESP32 Vue + Axios</title>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
 
  <!-- Our simple example APP -->
  <div id="app">
  <div>
    <button v-on:click="getAll()">GetAll</button>
  </div>
  <div>
    <button v-on:click="get()">Get</button>
    <input v-model="getId" placeholder="getId">
  </div>
  <div>
    <button v-on:click="getFiltered()">Filter</button>
    <input v-model="filter" placeholder="filter">
  </div>
  <div>
    <button v-on:click="create()">Create</button>
  </div>
    <div>
      <my-component v-for="item in items" v-bind:my="item" v-bind:key="item.id"></my-component>
   </div>
  </div>
 
  <!-- From CDN -->
  <!--<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>-->
  <!--<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js"></script>-->

  <script type="text/javascript" src="./vendor/vue.min.js"></script>
  <script type="text/javascript" src="./vendor/axios.min.js"></script>
    
  <!-- Load the files that simulate our API and our App in Vue.JS -->
  <script type="text/javascript" src="./js/API.js"></script>
  <script type="text/javascript" src="./js/app.js"></script>
</body>
</html>
Copied!

The VueJS application is defined in the ‘app.js’ file. It is very simple, and basically exposes a collection of ‘items’ objects, and the necessary methods to call our example API.

Vue.component('my-component', {
    props: ['my'],
    template: '<div>{{my.text}}<button v-on:click="get(my.id)">Get</button><button v-on:click="update(my.id)">Update</button><button v-on:click="replac(my.id)">Replace</button><button v-on:click="delet(my.id)">Delete</button></div>',
    methods: {
        get: function (id) {
            API_get(id);
        },
        
        update: function (id) {
            API_update(id, 'NewItem');
        },
        
        replac: function (id) {
            API_replace(id, 'NewItem');
        },
        
        delet: function (id) {
            API_delete(id);
        }
    }
})

var app = new Vue({
    el: '#app',
    data: {
        filter: "",
    getId: "",
        items: [
            { id: 0, text: 'Item1'},
            { id: 1, text: 'Item2' },
            { id: 2, text: 'Item3'}
        ]
    },
    
    methods: {
        getAll() {
            API_getAll();
        },
        
    get() {
            API_get(this.$data.getId);
        },
    
        getFiltered() {
            API_getFiltered(this.$data.filter);
        },
        
        create() {
            API_create('NewItem');
        },  
    }
})
Copied!

The API, which in turn is defined in the ‘API.js’ file. These functions use Axios to make the calls to our Rest API, as we saw in the previous post.

function API_get(id) {
    axios.get('item/' + id)
    .then(function (response) {
        console.log(response);
    })
    .catch(function (error) {
        console.log(error);
    })
    .then(function () {
    });
}

function API_getFiltered(filter) {
    axios.get('item', {
        params: {
            filter: filter
        }
    })
    .then(function (response) {
        console.log(response);
    })
    .catch(function (error) {
        console.log(error);
    })
    .then(function () {
    });
}

function API_getAll() {
    axios.get('item')
    .then(function (response) {
        console.log(response);
    })
    .catch(function (error) {
        console.log(error);
    })
    .then(function () {
    });
}

function API_create(data) {
    axios.post('item', {
        data: data
    })
    .then(function (response) {
        console.log(response);
    })
    .catch(function (error) {
        console.log(error);
    })
    .then(function () {
    });
}

function API_replace(id, data) {
    axios.put('item/ ' + id, {
        data: data
    })
    .then(function (response) {
        console.log(response);
    })
    .catch(function (error) {
        console.log(error);
    })
    .then(function () {
    });
}

function API_update(id, data) {
    axios.patch('item/ ' + id, {
        data: data
    })
    .then(function (response) {
        console.log(response);
    })
    .catch(function (error) {
        console.log(error);
    })
    .then(function () {
    });
}

function API_delete(id) {
    axios.delete('item/' + id)
    .then(function (response) {
        console.log(response);
    })
    .catch(function (error) {
        console.log(error);
    })
    .then(function () {
    });
}
Copied!

Result

We upload our new page to the SPIFFS memory, and when loading it in the browser we see the same page as before.

esp8266-vuejs-axios-web

If we interact with the buttons, we check in the browser’s developer console that the actions are performed correctly.

esp8266-vuejs-axios-console

As we can verify in the serial port terminal of the ESP8266 that, indeed, the actions and information are received correctly in the backend.

esp8266-vuejs-axios-serial

Even if the page is still visually simple, we have taken an important step in integrating more complex web applications served by the ESP32. We are no longer using plain JavaScript, but two very useful libraries such as Axios and VueJS.

With this, we already have a more maintainable foundation for building web interfaces that consume a REST API served from the device itself.

Download the code

All the code from this post is available for download on GitHub. github-full