In previous articles, we’ve discussed the basics of embedded systems web development, showing some fundamental concepts of HTML, CSS, and JS technologies. Although these are the pillars for any web-based application, nowadays, there’re a variety of options that we can choose from to create dynamic and attractive user interfaces in less time. These tools are known as frameworks, and in this article we’ll learn one which is very much in line with the requirements of embedded systems; this is Vue.
We’ll talk about how to implement Vue in your web interface projects using NetBurner devices, with a perspective focused on embedded systems developers with little to no experience in the world of web systems.
Introduction
Vue is an open-source framework for user interface design based on JavaScript. It was created by Evan You (a former Google employee) in 2014. It provides a declarative, component-based programming model that enables the creation of scalable applications for small and large projects.
At only seven years old, Vue is a younger framework compared to Angular (2010) and React (2013). However, that has not prevented it from gaining popularity among developers today. For example, companies such as Alibaba, Trivago, Netflix, and Adobe have started migrating some of their services to incorporate Vue.
Image 1 shows the popularity of VUE compared to Angular and React based on the number of stars on GitHub.

Why Vue?
We’ve already pointed out that Vue is not the only choice of frameworks we have for user interface design based on web technologies, so why choose Vue over Angular and React? This could be a never-ending discussion because each one has exciting features. In this article, we’ll focus on Vue because its features fit well with the requirements of embedded systems. We outline and examine some of those features below.
Learning Curve
For those who come from embedded systems development, starting with web development can be a nightmare due to the many tools and technologies out there. That’s why I consider the time it’ll take us to learn a new technology a vital point; we can’t afford to spend one year learning a tool that will surely be supplanted by newer technologies as soon as we master it.
Vue is easy to learn if you have the basics of HTML/CSS and JavaScript. You can start developing applications in a couple of months; if you are very dedicated, you could even start converting your old web projects to Vue in a few weeks.
But you must be careful. Even though it’s a simple framework to learn, the better your JavaScript proficiency, the better your Vue code will be. Poor code could make your application difficult to test and maintain.
Progressive Framework
This is one of the most interesting features of using Vue. It’s a progressive framework. That is, you can progressively migrate an application from another framework written with native HTML/CSS and JS.
What does this mean for us? This means that Vue can work in one section of your project, and everything else works with another technology without having conflict between the two pieces. Image 2 shows an example of this. Only one component (blue) is handled by Vue and everything else by another library or framework.

This is very useful for embedded systems because if you already have a working system and want to add more functionality, it’s enough to create a component managed by Vue without having to remake the complete application from scratch.
Documentation
One of the critical components to have when you start learning to use new technology is good documentation with which you can understand the specific topics. Vue provides well-organized documentation, starting from the basics and going to more advanced topics. You can find the documentation on the official Vue website. It contains everything you need to use this framework.
In addition to the official documentation, you can find various videos and tutorials on the web.
Versatility
This section describes some benefits of working with Vue. Unlike other frameworks, it offers certain freedoms, which allows for a high level of customization based on your coding style or your team’s standards.
Coding Language
Originally VUE ran on native JavaScript, making it very easy to use if you already knew how this programming language works. With Vue 3.0, you can also write code using Typescript, a JavaScript superset that allows you to add additional functionality. This includes adding variable typing, using interfaces, object-oriented code in an effortless way, etc.
API Styles
The creation of components in Vue can be done in two ways:
- Option API
- Composition API.
Options API: The traditional way of working with Vue is the one I strongly recommend starting with. It’s about organizing a component’s information in properties that contain the object. Through these properties, you add functionality to the application.
A component based on the Options API looks like this:
Composition API: This is the new way of creating components in VUE. Unlike the Options API, there’s only one attribute where all of the application’s functionality is placed. This allows it to have more fluid code, and the form is more similar to traditional JavaScript.
A component based on Composition API looks like this:
Once Vue is understood through the Options API, I recommend using the Composition API for all components created in the future. This is because you have more versatility in using the advanced features of Vue with this API.
How To use Vue with NetBurner Devices?
In this section, we’ll show how to use Vue on your favorite NetBurner board, so you can bring your next web-based user interface to the world quickly and easily. We’ve modified the existing default application for the MODM7AE70 development board, but it will work for any NNDK 3.x.x based board.
To demonstrate the progressiveness and ease of implementing Vue, we’ll change a small part of the code in the LED/Switch Control Example section to work with Vue. The remaining application will work as is without any changes. Image 3 below shows the current LED/Switch Control Example page, and enclosed in red is the section to which we’ll add Vue functionality.
Currently, the LED control section uses the CPPCALL dynamic web function, which is a handy feature. The problem is that for this to work, there must be a browser reload for the new value to be displayed, which may not be very appealing to the user. Although this can also be solved with WebSockets, we want to give you another option for your toolbox.

Build current example
The first thing you need to do is to compile and load (you can use NBEclipse or command line) the example, which can be found in:
\nburn\examples\PlatformSpecific\MODM7AE70\MODM7AE70\MODM7AE70FactoryApp
Open a web browser on your computer that is on the same network as your development board and access the IP of your device (this can be found by going to discover.netburner.com). You’ll see a page like the one shown in Image 4.

Adding an HTTP Endpoint
With the above, you have verified that your system is ready. Before you add Vue, first, you need to make some changes in the firmware. Add an HTTP endpoint to allow communication through the HTTP GET verb. To do this, go to the src/webfuncs.cpp
file and add the following code at the end.
/*---------------------------------------------------------------------------------------
* Callback to intercept a GET request for URL leds-vue*. The purpose of this callback
* is to change the status of the LEDs on the development board and get an echo of what
* is received.
*
* - Sends a JSON header to the browser to specify the content that follows is application/json
* - Change the status of the LEDs
* - Create a small JSON to respond with the current value sent.
* - A return value of 1 tells the system the HTML request was handled by the callback
*
* Notes:
* - HTTP_Request is a structure containing detailed information of the request
*--------------------------------------------------------------------------------------*/
int callbackGetLeds(int sock, HTTP_Request &pHttpRequest) {
iprintf("Executing GET request callback function: callbackPostLeds\r\n");
iprintf("Request URL: %s, from: %I\r\n", pHttpRequest.pURL, pHttpRequest.client_IPaddr);
// The URL will have the format: "leds-vue?number", where the value
// of "number" will store the LED information. The following code
// will test for the '?' character. If one exists, then the
// number following the '?' is assumed to contain a value
// indicating which LEDs are lit. If no '?' is in the URL, then
// the LEDs are initialized to a known state.
int32_t urlEncodeOffset = 9;
uint8_t v = 0xAA;
if ((*(pHttpRequest.pURL + urlEncodeOffset)) == '?') {
v = (uint8_t)atoi((char *)(pHttpRequest.pURL + urlEncodeOffset + 1));
}
putleds(v & 0xFF);
// Create respond string to client with the JSON Conten-Type
// And the JSON object with the value of the LEDs
char leds_string[50];
sprintf(leds_string, "{\"leds\":%u}", v & 0xFF);
writestring(sock, "HTTP/1.0 200 OK\r\nPragma: no-cache\r\nContent-Type: application/json\r\n\r\n");
writestring(sock, leds_string);
// Notify system we handled the GET request
return 1;
}
/*
* Declare the callback function. Parameters:
* leds-vue* URL to intercept
* callbackGetLeds Pointer to the callback function
* tGet HTTP Request Type (ref HTTP_RequestTypes)
* 0 User Access Group, 0 = no password
* true When to call (beforeFiles parameter):
* true: Always called for the specified URL
* false: Only called if the if the requested URL cannot be satisfied elsewhere
*/
CallBackFunctionPageHandler getHandlerLedsVue("leds-vue*", callbackGetLeds, tGet, 0, true);
This code adds an interceptor to the URLs with the format leds-vue*
, which calls a callback (callbackGetLeds
) that will be in charge of controlling the state of the LEDs on the development board.
Adding the VUE Library
VUE is a JavaScript library, so it’s added to the project with the
tag. There’re two ways to do this:
- Using a Content Delivery Network (CDN): This requires the system to have an internet connection but saves memory space on the microcontroller. You can find the source here.
- Embedded in the microcontroller flash: This does not require an internet connection but requires sufficient space available in the flash memory. The library minified for version 3.2.33 has an approximate weight of 160Kb.
In this article, we’ll use the embedded way. You can download the minified version of the library here. In your project, inside the html/js
folder, add a file called “vue.global.min.js” and paste the content of the Vue library.
Open the html/led.html file, and add the library obtained before at the end of the tag.
Adding the Vue Application Section
The library by itself does nothing. It is necessary to assign a space where the library will have domain. To do this, open the html/led.html
file and look for the following section
This current section controls the LEDs we want to replace, so delete it and add the following instead.
This section will be the one that will control VUE. This must be identified by a unique id which will be used later to tell VUE where the application will be executed (in this case, it’s called “app_vue”, but it can be any name). Outside this section, everything will continue to work the way it was before, and VUE will only be able to modify and read values within this area.
Adding VUE application code
Once the VUE work area is ready, it’s time to create the application code. To do this inside the html/js
folder, create a file called “vue-app.js” and copy the following code.
const { createApp } = Vue;
createApp({
/** Reactive data */
data() {
return {
leds: 0,
};
},
/** Methods */
methods: {
toggleLed(index) {
this.getLeds(this.leds ^ (1 << index));
},
async getLeds(value) {
// Create URL
let endpoint = "/leds-vue";
if (led >= 0) endpoint += `?${value}`;
// Send request over HTTP
const response = await fetch(endpoint);
const data = await response.json();
// Get the new value of leds
this.leds = data?.leds ?? 255;
},
getImageLedStatus(state) {
return `images/${state ? "on" : "off"}.png`;
},
},
/** LifeCycle */
mounted() {
this.getLeds(170);
},
}).mount("#app_vue");
This code has all the necessary functionality to change the status of the LEDs by using the following methods:
- getLeds: It is in charge of requesting and changing the status of the LEDs by sending an HTTP request through the endpoint “leds-vue?state” (which you previously configured in the board).
- toggleLed: Toggles the bit value of the corresponding LED and calls the getLeds function.
- getImageLedStatus: Gets the value of the image depending on the current state of the LED.
- mounted: Vue hook executed when the application is already mounted in the web client.
At the end, you can see the mount method, which specifies the ID of the HTML section where this application will be mounted; this value must be the same that you assigned in the previous step.
For all this to work, it’s necessary to open the html/led.html
file and add the application file at the end of the tag.
Adding the Vue Application to HTML
To finish, the only thing you have to do is execute the methods created before. To do this, add the following HTML inside the app_vue
section within the html/led.html
file. This is necessary to create the LEDs and give them functionality.
![]()
Testing Code
Everything is ready, just recompile the project. It’s recommended to do a clean build. Once the code is loaded onto the development board, test the new function of the LEDs. Now without refreshing the page, you’ll see the change in the state of the LED.
Wrapping Up
Vue is an easy framework to implement in our current projects and designs. While it’s required to know the syntax and features to use, the good news is that there’re many courses, tutorials, and excellent documentation on how to use it. One of the main advantages is that we do not have to redesign our entire UI from scratch. Instead, we can gradually change the features you want to modify or add more interaction.
We hope this article will be helpful so that you can add a more dynamic UI using NetBurner devices and Vue in your future applications and projects.
We would like to hear from you, don’t be a stranger and let us know what topics you would like to see in future articles! If you would like to share a project you are working on, you can drop us a comment below, or if you want to contact us directly, feel free to do it here.
About the Autor

Jordan Garcia
Senior Embedded Firmware Developer at Luxoft.
IoT, embedded firmware, and industrial automation enthusiast.
Reader, dancer, swimmer, and dog lover.