Hello Everyone,
I am watching the FreeMASTER training videos, and practising the exercises along.
At the moment I am watching the following training video.
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)
Thanks in advance.
Solved! Go to Solution.
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
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
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)
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>