Implementing a Control HTML Page with FreeMaster and JSON-RPC API

cancel
Showing results for 
Search instead for 
Did you mean: 

Implementing a Control HTML Page with FreeMaster and JSON-RPC API

Implementing a Control HTML Page with FreeMaster and JSON-RPC API

Introduction

FreeMaster allows us to create HTML pages with Javascript to interact with our embedded application, and access the FreeMaster features, allowing us to create complex and personalized user interfaces. FreeMaster gives us two options for rendering and communicating our HTML page: Internet Explorer or a Chromium rendering engine. The Chromium rendering engine (which is the base for modern browsers like Google Chrome, Microsoft Edge, and Opera)  is the more modern option, supporting asynchronous JavaScript programming and other modern scripting technologies.

The Chromium rendering uses the JSON-RPC protocol to call the procedures on FreeMaster. JSON-RPC is a remote procedure call protocol that use JSON to encode its data, in this case, is used to call procedures from the FreeMaster application,

 FreeMaster gives us a JSON-RPC API for Javascript that facilitates the communication between the HTML page and FreeMaster.

Browser (Chromium engine) 

FreeMaster_JSON_API.PNG

Example Description

In this example, we are going to use the JSON-RPC API to connect an HTML page to FreeMaster. The HTML page will be capable of reading a variable and modifying a variable, the HTML page will also plot the read variable. This example is based on a FreeMaster project that calculates the value of a sine line based on an angle that is constantly incrementing, you can find the description of the project in How To implement an interface using FreeMaster.

Hardware / Software used

Hardware setup:

Board Used: FRDM-K64F

SDK: SDK_2.x_FRDM-K64F  Version 2.8.0 or later

 

Software setup:

Board Application developed in: MCUXpresso IDE v11.2.0

FreeMaster Version: FreeMaster  3.0.2.6

Control Page (HTML, CSS, Javascript) developed with: Visual Studio Code 1.48.0 (this was the IDE used for developing the control page but you can use any IDE of your preference)

Graphs library: Chartist.js

Official page: https://gionkunz.github.io/chartist-js/

 

HTML page Example (without FreeMaster)

For this example, the HTML page we want to connect with FreeMaster looks like this:

HTML_Page_FreeMaster.PNG

This document is not meant to teach you how to design or create an HTML page, but to connect the HTML page with our FreeMaster project. The elements of our HTML page that will communicate with the FreeMaster Project through the JSON-RPC API are the next:

  • Connect Button: The connect button will star communication with the board and the FreeMaster project.
  • Start Measure Button: The measure button will start the reading operation for the sin_value variable.
  • Angle Step Modifier: This input will write the angle_step variable in our project.
  • Graph: The graph will plot the sin_value that has been read.

 

General Structure of the Project

The two files that we are going to be working with will be our HTML file and our Javascript file, in this example we are going to name them index.html and index.js, we will add more required files as we keep going through the document. If you are using Visual Studio open the folder that will contain the files, you can add or create files in the Explorer tab:

 
vscode_example.png

 

 In index.html, make sure that index.js is being imported (you can check at the end of the body element):

<script type="text/javascript" src="./index.js"></script>

Connect our HTML page with FreeMaster (Use of freemaster-client.js)

FreeMaster provides us with a “freemaster-client.js”  file available in the FreeMaster installation folder. This file is based in a popular JSON-RPC javascript library for generating and parsing messages called “simple-jsonrpc-js”, this implementation is also found in the installation folder and you can find the full documentation here: https://github.com/jershell/simple-jsonrpc-js.

To connect our HTML page with the FreeMaster application using the JSON-RPC interface we need to use a Javascript wrapper object that contains all the methods of the JSON-RPC API. The object is named as PCM and it is declared in the “freemaster-client.js” file, we access the API methods through the PCM object.

In resume:

 

table_json_rpc.PNG

 The complete address of the “freemaster-client.js” and the “simple-jsonrpc-js” in the installation folder is:

C:\nxp\FreeMASTER 3.0\FreeMASTER\examples\scripting\JavaScript-JSON-RPC

export_folder.PNG

We will need these files to connect to our HTML page with FreeMaster, copy the files to your HTML page project:

 
import_example.png

 

Now we need to import the files “freemaster-client.js” and “simple-jsonrpc-js.js” in index.html,  on the header of the document we write:

  <script type="text/javascript" src="/js/simple-jsonrpc-js.js"></script>
  <script type="text/javascript" src="/js/freemaster-client.js"></script>

Next, we need to instantiate the Javascript wrapper object that we import in the “freemaster-client.js”. To do that, you need to create an external Javascript file and import it in our HTML document or implement it inside a script element in the HTML document.

The wrapper object is named PCM, the implementation of the PCM object in the freemaster-client.js file looks requires the following arguments:

var PCM = function(url, onSocketOpen, onSocketClose, onSocketError)

 

The url refers to the direction of the web server we are going to connect, when we open the FreeMaster application it initializes the JSON-RPC server listening on port number 41000. So our url should be “localhost:41000”.  The next three arguments ask for handlers to execute when connecting to the server when the server is close and a handler in case an error occurs during communication. To use these handlers we first need to create them, in the form of Javascript functions and then we can pass them like callbacks (a function pass it as an argument to another function).

So our instantiation should look something like this (in index.js

let pcm = new PCM("localhost:41000", on_connected, on_close, on_error);

function on_connected() {
  console.log("Connected to WebSocket");	
};

function on_error() {
  console.log("Error with the WebSocket");
};

function on_close() {
  console.log("WebSocket Close");
}

Here we use our on_connected, on_close, and on_error functions as handlers. The on_close and on_error functions only print a message on the console when they are executed. The on_connected method is also printing a message indicating that the connection to the JSON-RPC server was successful.

The next thing we have to do is use some of the JSON-RPC methods to give functionality to the HTML page, showing and modifying the variables from our embedded application. In the next section, we are going to explain how the JSON-RPC API methods are used.

Useful JSON-RPC API methods

The full list of JSON-RPC API methods (as well as the ActiveX methods) can be found in the FreeMaster User Guide:FreeMaster User Guide

We access to the JSON-RPC API methods through the PCM wrapper object. The API methods return a javascript Promise object, a Promise object represents an asynchronous operation, (like remote calls to FreeMaster) and we can indicate what to do in case of success or failure of the operation. The resolution of our asynchronous operation will be contained in a response object, and in the case of the JSON-RPC API, the output values of our operation will be in the data member of the response object, there is also another member named xtra that contains different values (like confirmation values) or alternative formatting to the response, check the user guide for more information of the returned value of xtra, but mostly we are going to use the data member.

An example of the use of Promise with the JSON-RPC methods can be seen here:

pcm.GetAppVersion()
    //In case of success we print the output value (data member of response object)
    .then((response) => console.log("App version: " + response.data))
    //In case of failure we print the response object
    .catch((err) => console.log(err))

 

The then method is used in case of success and the catch method in case of failure. Both methods receive a callback function that receives the response object to indicate what to do with the response in each case.

Some useful methods of the JSON-RPC API are listed below:

table_api.PNG
 

A full list can be found here:  FreeMaster User Guide.

A more deep look at Promises in Javascript can be found in the official MDN Web Documents: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise.

Implementing the JSON-RPC API in our HTML page

In this section, we are going to exemplify some of the methods (StartComm, StopComm, ReadVariable, WriteVariable) that our PCM wrapper object offers. To give our HTML elements functionality we need to select them and add an event listener to them using DOM manipulation, in our script. Next is a simple example on how to do this, but for a more in-depth explanation check out the MDN Web Documentation: https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction.

DOM Manipulation example

In our HTML script (index.html), the connect button element is described like this:

<button id = "connectBtn" type="button" class="btn btn-success"> <i class="fas fa-wifi    "></i> Connect</button>

 

To select the button element in our Javascript script we use the id attribute of our element:

let conButton = document.getElementById("connectBtn");

 

Finally, we add an event listener to give our HTML element functionality:

promise_example.png

Using the API Methods

In this next section, we are going to use some of the methods that the JSON-RPC API offers us and apply DOM manipulation to use them in conjunction with our HTML elements. The following examples will be written in our javascript script, in this case, index.js (you can also add this in a script element at the end of the body section of your HTML file if you prefer it).

The methods that we are going to connect with our HTML elements through DOM manipulation are the next:

HTML element

HTML name (DOM manipulation)

API methods

Function

 
connect_button.png

conButton 

StartComm and StopComm

Start or stop the communication with the board.

 
meas_button.png

measureButton

ReadVariable

Read a variable from our embedded application, in this case the value of our sine line.

 
input_step.png

inputAngle

WriteVariable

Write the value of a variable from our embedded application, in this case the increment between calculations of our sine line.

 

API Methods: StartComm and StopComm Example

The StartComm and StopComm methods open and close the communication port. They receive the name of the port as an argument, the special name “preset” identifies the default connection built in the FreeMASTER desktop application.

In our example, we are going to use these methods in index.js when we click the connect button, as you can see we obtain the button with DOM manipulation and use the methods in the event listener.

connect_button.png
 

At index.js

let conButton = document.getElementById("connectBtn");
let connection = false;

conButton.addEventListener("click", (ev) => {
    if(!connection)
    {
        pcm.StartComm("preset");  
    }
    else
    {
        pcm.StopComm("preset");
    }
    connection = !connection;  
})

 

API Methods: ReadVariable Example

The ReadVariable method allows us to read one of the variables in our embedded application. The method receives the name of the variable that we want to read as an argument.  The response object contains the value of the variable.

In our example, we are going to start reading the “sin_value” variable when clicking in the “Start Measure” button, we are also going to set an interval for reading that variable every 100 milliseconds.

meas_button.png
 

At index.js

let measureButton = document.getElementById("measureBtn");

measureButton.addEventListener("click", (ev) => {
    //The setInterval function receives a callback function and the time of repetition	
intervalId =  setInterval(() => {
      pcm.ReadVariable("sin_value")
      .then((response) => {
        console.log(response.data);
      })
      .catch((err) => {});
    }, 100);
})

 

API Methods: WriteVariable Example

The WriteVariable method allows us to write to one of the variables in our embedded application. The methods receive the name of the variable to change and the new value. The response object returns a boolean value if the operation was successful.

In our example, we are going to use this method when modifying the “Angle Step” for the input box, to write in the “angle_step” variable.

input_step.png

At index.js

let inputAngle = document.getElementById("angleStep");

inputAngle.addEventListener("change", (ev) => {
  pcm.WriteVariable("angle_step", inputAngle.value);
})

 

At the end of the index.js file should look something like this:

let pcm = new PCM("localhost:41000", on_connected, on_close, on_error);

function on_connected() {
  console.log("Connected to WebSocket");

};

function on_error() {
  console.log("Error with the WebSocket");
};

function on_close() {
  console.log("WebSocket Close");
}

let conButton = document.getElementById("connectBtn");
let connection = false;

conButton.addEventListener("click", (ev) => {
    if(!connection)
    {
        pcm.StartComm("preset");  
    }
    else
    {
        pcm.StopComm("preset");
    }
    connection = !connection;  
})

let measureButton = document.getElementById("measureBtn");

measureButton.addEventListener("click", (ev) => {
    //The setInterval function receives a callback function and the time of repetition  
intervalId =  setInterval(() => {
      pcm.ReadVariable("sin_value")
      .then((response) => {
        console.log(response.data);
      })
      .catch((err) => {});
    }, 100);
})

let inputAngle = document.getElementById("angleStep");

inputAngle.addEventListener("change", (ev) => {
  pcm.WriteVariable("angle_step", inputAngle.value);
})

 

Graphs

One thing that we probably want to have in our HTML page, are graphs to show the data from our embedded application. There exist multiple graphs and plotting libraries/modules made for javascript, the one to use truly depends on the requirements of the application, and the preference of who is developing the HTML page. For this example, we are going to use Chartist.js just to show the capabilities that you have using an HTML page with FreeMaster, but feel free to use the library of your preference.

The next example will show the use of the JSON-RPC API with a graph library, take into consideration that we are using the Chartist.js for any other libraries/module check the corresponding documentation.

Implementing Chartist

In the HTML script (index.html), we need to import the Javascript and CSS files from chartists, you can download it from the Chartist official github repositoryhttps://github.com/gionkunz/chartist-js/tree/master/dist.  Or you can look at different alternatives for downloading it in the official page: https://gionkunz.github.io/chartist-js/getting-started.html

In the head section of the HTML page we import the files:

    <link rel="stylesheet" href="./chartist.css">
    <script type="text/javascript" src="./chartist.min.js"></script>

In the body section, we can insert the chart element like this:

 <div class="ct-chart ct-major-twelfth"></div>

The charts in chartist take an object that contains the data, which must consist of two series describing the data and the labels on the X-axis. Another object can be given indicating the values of the Y-axis.

In the Javascript script (index.js) we write this at the beginning of the document:

chartist_code_example.png
let data = {
    labels: Array(50).fill(''),
    series: [
        Array(50).fill(0)
    ]
};

let options = {
    high: 1,
    low: -1
};

let chart = new Chartist.Line('

 

Now, to update our chart with the values that we are reading from our board we are going to modify the event listener that we create for our Measure Button, instead of printing the response of our ReadVariable method, we are going to use the response to update the data object of our chart:

chartis_implementation_example.png
let measureButton = document.getElementById("measureBtn");

measureButton.addEventListener("click", (ev) => {
    //The setInterval function receives a callback function and the time of repetition	
intervalId =  setInterval(() => {
      pcm.ReadVariable("sin_value")
      .then((response) => {
        data.series[0].shift();
        
        data.series[0].push(response.data);

        chart.update(data);
      })
      .catch((err) => {});
    }, 100);
})

With this, we have set up the chart to update the values of our embedded application. Again, this is specific for the Chartist.js library, although it can serve as a reference for other libraries.

Running the HTML Page in FreeMaster Desktop Application

We can run our HTML Page either in our browser or in the FreeMaster Desktop Application.

Opening in the Browser

To run in the browser open the FreeMaster project in the FreeMaster Desktop Application and then open the HTML page in the browser:

page_running.png
 

Opening in the FreeMaster Browser Application

For the FreeMaster Desktop Application, we need to go to the options of our FreeMaster Project:

opening.PNG

Go to the HTML page section, there select the HTML file in the “Control page URL” input, and then select the “Chromium Embedded Framework” in the HTML Rendering Engine option:

select.pngfree_page.png

 

Conclusion

We can use HTML pages empowered with Javascript to create a powerful and customizable user interface taking advantage of the extensive tools that exist for Javascript. The API that FreeMaster offers for connecting our page with our embedded application allows us to create these pages easily without sacrificing the functionalities that we have with FreeMaster. Feel encouraged to check all the methods that the API offers and explore all the things that you can do with it. 

Attachments
Version history
Revision #:
1 of 1
Last update:
‎09-17-2020 11:41 AM
Updated by:
 
Contributors