Introduction to Dashboard using HTML, JavaScript & JSON-RPC Exercise Project Download

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Introduction to Dashboard using HTML, JavaScript & JSON-RPC Exercise Project Download

Jump to solution
1,425 Views
arun07
Contributor III

Hello Everyone,

I am watching the FreeMASTER training videos, and practising the exercises along.

At the moment I am watching the following training video.

Introduction to FreeMASTER Dashboard Coding Using HTML, JavaScript, ActiveX and JSON-RPC | NXP Semic...

And in this training video, in exercise 4, a dashboard is created where "Guage" is used to display the "var16" variable value and "Slider" is used to control/change the value of "var16inc".

I am not able to find the example project, so based on the video I tried to follow the steps. (Exercise-1, 2 and 3 are working fine, but with Exercise 4 I am facing a problem)

If someone can please provide me with the whole FreeMASTER project then it would be really great, else I am also sharing the problem here, maybe someone can help me in finding and fixing the problem.

For me, the "Guage" is working fine, but as I am adding the "Slider", the "Slider" appears and then disappears.

If I am commenting out the "Guage", "Slider" started appearing but the "on_slide" function is not getting called.

Below is my "main.html" code.

<!DOCTYPE html>
<html>
<head>
  
  <!-- load JSON-RPC and FreeMASTER wrapper object -->
  <script type="text/javascript" src="./simple-jsonrpc-js.js"></script>
  <script type="text/javascript" src="./freemaster-client.js"></script>
  <script type="text/javascript" src="./jquery.min.js"></script>
  <script type="text/javascript" src="./gauge.min.js"></script>
  <script type="text/javascript" src="./rangeslider.min.js"></script>
  <script type="text/javascript">
    
    let pcm;  // the main FreeMASTER communication object

    let gauge;
    var slider;
    let i_var16inc;

    function startup()
    {
      /* Desktop FreeMASTER listens on port 41000 by default, unless this is
       * overridden on command line using /rpcs option. FreeMASTER Lite 
       is configurable. */
      pcm = new PCM("localhost:41000", on_connected, on_error, on_error);
      pcm.OnServerError = on_error;
      pcm.OnSocketError = on_error;
    }

    function on_connected() 
    {
      /* Typically, you want to enable extra features to make use of the full API 
       * provided by desktop application. Leave this disabled and avoid any extra 
       * features when creating pages compatible with FreeMASTER Lite. */
      //pcm.EnableExtraFeatures(true);

      // Start timer
      setInterval( timer, 500);

      // load gauge
      load_gauge();
      i_var16inc = document.getElementById("input_var16inc");
      // slider
      slider = $('#slider');
      slider.rangeslider( {polyfill: false, onSlide: on_slide});
      
    }

    function on_error(err) 
    {
      /* Erors are reported in the status field. */
      // document.getElementById("status").innerHTML = err;
      /* Log Erros to console */
      console.log(err);
    }
    
    function read_variable(name, span_id)
    {
      /* ReadVariable uses FreeMASTER variable object from current project. Use 
       * ReadUIntVariable to access the memory directly using a symbol name. */
      return pcm.ReadVariable(name)
                .then((value) => { 
                  document.getElementById(span_id).innerHTML = value.data;
                })
                .catch((err) => { 
                  on_error(err.msg);
                });
    }
    
    
    function write_variable(name, input_id)
    {
      var val = document.getElementById(input_id).value;

      /* WriteVariable uses FreeMASTER variable object from current project. Use 
       * WriteUIntVariable to access the memory directly using a symbol name. */
      pcm.WriteVariable(name, val)
        .then(() => { 
          document.getElementById("span_status").innerHTML = "Write of the " + name + " succeeded.";
        })
        .catch((err) => { 
          on_error(err.msg);
        });  
    }

    function load_gauge()
    {
      let opts = 
      {
        angle: 0,                 // The span of the gauge arc
        lineWidth: 0.5,           // The line thickness
        radiusScale: 1,           // Relative radius
        pointer: 
        {
          length: 0.6,            // Relative to gauge radius
          strokeWidth: 0.035,     // The thickness
          color: '#000000'        // Fill color
        },
        // Static zones
        // When separating the background sectors or zones to have static colors
        // you must supply the staticZones property in the Gauge object's options.
        staticZones: 
        [
          {strokeStyle: "#30B32D", min: 100,    max: 30000}, 
          {strokeStyle: "#FFDD00", min: 30000,  max: 55000},
          {strokeStyle: "#F03E3E", min: 55000,  max: 65535}
        ],

        limitMax: false,          // If false, max value increases automatically if value > maxValue
        limitMin: false,          // If true, the min value of the gauge will be fixed
        colorStart: '#6FADCF',    // Colors
        colorStop: '#8FC0DA',     // just experiment with them
        strokeColor: '#E0E0E0',   // to see which ones work best for you
        generateGradient: true,
        highDpiSupport: true,     // High resolution support

        // Tick marks
        // Now you may also add Ticks on two levels, major and minor 
        // (or divisions and sub divisions).
        // renderTicks options:
        // divisions This is the number of major divisions around your arc.
        // divWidth This is to set the width of the indicator.
        // divLength This is a fractional percentage of the height of your arc line (0.5 = 50%)
        // divColor This sets the color of the division markers
        // subDivisions This sets the minor tick marks count between major ticks.
        // subLength This is a fractional percentage of the height of your arc line (0.5 = 50%)
        // subWidth This is to set the width of the indicator.
        // subColor This sets the color of the subdivision markers
        renderTicks: 
        {
          divisions: 5,
          divWidth: 1.0,
          divLength: 0.4,
          divColor: '#333333',
          subDivisions: 3,
          subLength: 0.2,
          subWidth: 0.5,
          subColor: '#666666'
        }
      };
      let target = document.getElementById('gauge_canvas');   // your canvas element
      gauge = new Gauge(target).setOptions(opts);             // create sexy gauge!
      gauge.maxValue = 65535;                                 // set max gauge value
      gauge.setMinValue(0);                                   // Prefer setter over gauge.minValue = 0
      gauge.animationSpeed = 32;                              // set animation speed (32 is default value)
      gauge.set(1250);                                        // set actual value
      gauge.set(10);
      gauge.set(100);
      gauge.set(200);
      gauge.set(400);
      gauge.set(800);
    }

    function timer()
    {
      read_variable("led_state", "span_led_status");
      read_variable("var16", "span_var16");
      // updating the gauge
      pcm.ReadVariable("var16")
        .then((response) => {
          // console.log("var16="+response.data);
          // gauge.set(response.data);
        })
        .catch((err) => console.log(err))
    }

    function ChangeIncrement()
    {
      write_variable("var16inc", "input_var16inc");
    }

    function on_slide( position, value )
    {
      console.log("I am here");   // not reaching here
      if( i_var16inc.value != value )
      {
        console.log("on_slide pos="+position+" value="+value);
        i_var16inc.value = value;
      }
    }
    
    </script>

<title>Hello World</title>
</head>

<body onload="startup()">
  <h1>Hello World Dashboard</h1>
  <h2>Using JSON-RPC</h2>

  Led Status: <span id="span_led_status">??</span>
  <br>
  <br>
  var16: <span id="span_var16">??</span>
  <br>
  <br>
  var16inc: <input type="text" id="input_var16inc" value="1" size=10>
  <input type="button" value="Write!" onclick="ChangeIncrement()">
  <span id="span_status" type="text"></span>
  <br>
  <br>

  <div style="width: 300px; text-align: center;">
    <canvas id="gauge_canvas"></canvas>
  </div>
  <br>
  <br>

  <div style="width: 300px; text-align: center;">
    <input style="width: 300px;" id="slider" type="range" min="1" max="10" step="1" value="1">
  </div>
  

</body>
</html>

The following is the GIF image showing the issue. (Most probably this looks like an HTML JavaScript, but maybe someone can help me out here)

FreeMASTER_Dashboard_NotWorking.gif

Thanks in advance.

Tags (1)
0 Kudos
1 Solution
1,412 Views
MichalH
NXP Apps Support
NXP Apps Support

Hello,

the rangeslider example was taken from the original author here: https://rangeslider.js.org/  Refer to the example code and documentation there.

I think you miss the CSS stylesheet which is required not only to define a look of the slider and its handle, but also to define a positioning behavior.

Please see the HTML and CSS files of the exercise 4 attached.

Best regards,
Michal

 

 

View solution in original post

3 Replies
1,413 Views
MichalH
NXP Apps Support
NXP Apps Support

Hello,

the rangeslider example was taken from the original author here: https://rangeslider.js.org/  Refer to the example code and documentation there.

I think you miss the CSS stylesheet which is required not only to define a look of the slider and its handle, but also to define a positioning behavior.

Please see the HTML and CSS files of the exercise 4 attached.

Best regards,
Michal

 

 

1,402 Views
arun07
Contributor III

Thank You for sharing the files.
I still can't figure out the problem associated with my source files.
But I tested the files shared by you and they work fine. I will compare my source files with yours and will figure out the problem. Many Thanks (Will accept the answer after I am to find the problem)

0 Kudos
1,395 Views
arun07
Contributor III

Thank You, as you mentioned, the style sheet was the one problem that is fixed now.
The updated HTML code is as below.

<!DOCTYPE html>
<html>
<head>
  
  <link href="styles.css" rel="stylesheet">
  <!-- load JSON-RPC and FreeMASTER wrapper object -->
  <script type="text/javascript" src="./simple-jsonrpc-js.js"></script>
  <script type="text/javascript" src="./freemaster-client.js"></script>
  <script type="text/javascript" src="./jquery.min.js"></script>
  <script type="text/javascript" src="./gauge.min.js"></script>
  <script type="text/javascript" src="./rangeslider.min.js"></script>
  <script type="text/javascript">
    
    let pcm;  // the main FreeMASTER communication object

    let gauge;
    var slider;
    let i_var16inc;

    function startup()
    {
      /* Desktop FreeMASTER listens on port 41000 by default, unless this is
       * overridden on command line using /rpcs option. FreeMASTER Lite 
       is configurable. */
      pcm = new PCM("localhost:41000", on_connected, on_error, on_error);
      pcm.OnServerError = on_error;
      pcm.OnSocketError = on_error;
    }

    function on_connected() 
    {
      /* Typically, you want to enable extra features to make use of the full API 
       * provided by desktop application. Leave this disabled and avoid any extra 
       * features when creating pages compatible with FreeMASTER Lite. */
      //pcm.EnableExtraFeatures(true);

      // Start timer
      setInterval( timer, 500);

      // load gauge
      load_gauge();
      i_var16inc = document.getElementById("input_var16inc");
      // slider
      slider = $('#slider');
      slider.rangeslider( {polyfill: false, onSlide: on_slide});
    }

    function on_error(err) 
    {
      /* Erors are reported in the status field. */
      // document.getElementById("status").innerHTML = err;
      /* Log Erros to console */
      console.log(err);
    }
    
    function read_variable(name, span_id)
    {
      /* ReadVariable uses FreeMASTER variable object from current project. Use 
       * ReadUIntVariable to access the memory directly using a symbol name. */
      return pcm.ReadVariable(name)
                .then((value) => { 
                  document.getElementById(span_id).innerHTML = value.data;
                })
                .catch((err) => { 
                  on_error(err.msg);
                });
    }
    
    
    function write_variable(name, input_id)
    {
      var val = document.getElementById(input_id).value;

      /* WriteVariable uses FreeMASTER variable object from current project. Use 
       * WriteUIntVariable to access the memory directly using a symbol name. */
      pcm.WriteVariable(name, val)
        .then(() => { 
          document.getElementById("span_status").innerHTML = "Write of the " + name + " succeeded.";
        })
        .catch((err) => { 
          on_error(err.msg);
        });  
    }

    function load_gauge()
    {
      let opts = 
      {
        angle: 0,                 // The span of the gauge arc
        lineWidth: 0.5,           // The line thickness
        radiusScale: 1,           // Relative radius
        pointer: 
        {
          length: 0.6,            // Relative to gauge radius
          strokeWidth: 0.035,     // The thickness
          color: '#000000'        // Fill color
        },
        // Static zones
        // When separating the background sectors or zones to have static colors
        // you must supply the staticZones property in the Gauge object's options.
        staticZones: 
        [
          {strokeStyle: "#30B32D", min: 100,    max: 30000}, 
          {strokeStyle: "#FFDD00", min: 30000,  max: 55000},
          {strokeStyle: "#F03E3E", min: 55000,  max: 65535}
        ],

        limitMax: false,          // If false, max value increases automatically if value > maxValue
        limitMin: false,          // If true, the min value of the gauge will be fixed
        colorStart: '#6FADCF',    // Colors
        colorStop: '#8FC0DA',     // just experiment with them
        strokeColor: '#E0E0E0',   // to see which ones work best for you
        generateGradient: true,
        highDpiSupport: true,     // High resolution support

        // Tick marks
        // Now you may also add Ticks on two levels, major and minor 
        // (or divisions and sub divisions).
        // renderTicks options:
        // divisions This is the number of major divisions around your arc.
        // divWidth This is to set the width of the indicator.
        // divLength This is a fractional percentage of the height of your arc line (0.5 = 50%)
        // divColor This sets the color of the division markers
        // subDivisions This sets the minor tick marks count between major ticks.
        // subLength This is a fractional percentage of the height of your arc line (0.5 = 50%)
        // subWidth This is to set the width of the indicator.
        // subColor This sets the color of the subdivision markers
        renderTicks: 
        {
          divisions: 5,
          divWidth: 1.0,
          divLength: 0.4,
          divColor: '#333333',
          subDivisions: 3,
          subLength: 0.2,
          subWidth: 0.5,
          subColor: '#666666'
        }
      };
      let target = document.getElementById('gauge_canvas');   // your canvas element
      gauge = new Gauge(target).setOptions(opts);             // create sexy gauge!
      gauge.maxValue = 65535;                                 // set max gauge value
      gauge.setMinValue(0);                                   // Prefer setter over gauge.minValue = 0
      gauge.animationSpeed = 32;                              // set animation speed (32 is default value)
      gauge.set(1250);                                        // set actual value
      gauge.set(10);
      gauge.set(100);
      gauge.set(200);
      gauge.set(400);
      gauge.set(800);
    }

    function timer()
    {
      read_variable("led_state", "span_led_status");
      read_variable("var16", "span_var16");
      // updating the gauge
      pcm.ReadVariable("var16")
        .then((response) => {
          // console.log("var16="+response.data);
          gauge.set(response.data);
        })
        .catch((err) => console.log(err))
    }

    function ChangeIncrement(update_slider)
    {
      write_variable("var16inc", "input_var16inc");
	  if (update_slider)
	  {
		// update the slider also
		slider.val(i_var16inc.value).change();
	  }
    }

    function on_slide( position, value )
    {
      console.log("I am here");   // not reaching here
      if( i_var16inc.value != value )
      {
        console.log("on_slide pos="+position+" value="+value);
        i_var16inc.value = value;
		ChangeIncrement(false)
      }
    }
    
    </script>

<title>Hello World</title>
</head>

<body onload="startup()">
  <h1>Hello World Dashboard</h1>
  <h2>Using JSON-RPC</h2>

  Led Status: <span id="span_led_status">??</span>
  <br>
  <br>
  var16: <span id="span_var16">??</span>
  <br>
  <br>
  var16inc: <input type="text" id="input_var16inc" value="1" size=10>
  <input type="button" value="Write!" onclick="ChangeIncrement(true)">
  <span id="span_status" type="text"></span>
  <br>
  <br>
  
  <div style="width: 300px; text-align: center;">
    <input style="width: 300px;" id="slider" type="range" min="1" max="10" step="1" value="1" data-orientation="horizontal" data-rangeslider>
  </div>
  
  <div style="width: 300px; text-align: center;">
    <canvas id="gauge_canvas"></canvas>
  </div>
  <br>
  <br>

</body>
</html>
0 Kudos