In this blog post, I will show how easy it is to write a live chart with Perl, Mojolicious::Lite and some javascript (mainly Highcharts).
The code
The Mojolicious::Lite very small webapp. With routes and get/set urls:
use Mojolicious::Lite;
my $datfile = "/tmp/values.txt";
# Answer to /
get '/' => sub {
my $c = shift;
$c->render(template => 'live', format => 'html');
};
# Set value from GET call
get '/setvalue/:value' => sub {
my $c = shift;
my $value = $c->param('value');
open(my $fh, '>', $datfile) or die "Could not open $datfile $!";
print $fh "$value\n";
close $fh;
$c->render(text => "You set the value to $value");
};
# Get value from GET call
get '/getvalue' => sub {
my $c = shift;
open(my $fh, '<:encoding(UTF-8)', $datfile) or die "Could not open '$datfile' $!";
my $value = <$fh>;
chomp $value;
$c->render(text => "$value");
};
Right below, I start the application:
app->start;
And open the __DATA__
section (where falls the template/view in Mojolicious::Lite applications):
__DATA__
And the view, with jquery and highcharts to make it "live".... Yes it is a bit a big blob since there is all configs for the chart, but it's not that complicated !
The view is a big chunk of javascript and an almost empty piece of html (just one div
to make room to chart):
@@ live.html.ep
<html lang="us">
<head>
<meta charset="utf-8">
<title>Dynamic Live Chart</title>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script>
$(document).ready(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
var chart;
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'spline',
marginRight: 10,
events: {
load: function() {
// set up the updating of the chart each second
var series = this.series[0];
var y = 0;
setInterval(function() {
var x = (new Date()).getTime(); // current time
$.get('/getvalue', function(data) {
var oldy = y;
y = parseInt(data);
series.addPoint([x, y], true, true);
});
}, 1000);
}
}
},
title: {
text: 'Dynamic Chart live'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Values'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
plotOptions: {
line: {
marker: {
enabled: false
}
}
},
tooltip: {
formatter: function() {
return '<b>'+ this.series.name +'</b><br/>'+
Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) +'<br/>'+
Highcharts.numberFormat(this.y, 2);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Value',
data: (function() {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -19; i <= 0; i++) {
data.push({
x: time + i * 1000,
y: 0,
});
}
return data;
})()
}]
});
});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
We have our application, now we are ready to feed and test 😃
Feed with random data
As you can see, the data source is a flat /tmp/values.txt
file that can be fed by http GET call or manually (this is what we will do right now):
$ while true; do echo `shuf -i 0-20 -n 1` > /tmp/values.txt; sleep 1; done
Start it and test
I start it with development server morbo
(but could be something else):
$ morbo live.pl
We can access value with:
$ curl http://127.0.0.1:3000/getvalue
12
Or set value to 100 for instance with the endpoint /setvalue/100
:
$ curl http://127.0.0.1:3000/setvalue/100
You set the value to 100
The result
Open your favorite browser and you will get this beautiful live chart:
You can also get an overview here
Top comments (9)
Great article
Both Mojolicious and Highcharts are awesome, we use both at work, but the license for Highcharts is a bit restricted. Recommendations for a freely distributable open source charting library would be most welcome... 😜
I use Apache Echarts
echarts.apache.org/en/index.html
Thank you for the tip, Echarts looks very nice !! But can you create live charts with it ?
Here is an example from the documentation:
echarts.apache.org/examples/en/edi...
Hi Roberto
I heard about echarts on a podcast, it just seemed a bit overkill compared to what I need to implement, I will give it a second look.
Take care
Hi,
In Mojolicious i have a html with echarts js code and I fill in the data variable and few others I need, through the stash. Very efficient in my use case.
By the way, in my opinion, Echarts can be an interesting solution for a Perl programmer to create high quality plots. Unfortunately a good/modern and complete plotting module is one of the things that Perl lacks.
Best regards
Hi Roberto, you mean as in server side rendering. I must admit I am not to the approach your outline of having the rendering done by the client, having the Mojolicious (or similar) service only deliver the raw data.
Guess I have been in the MVC-sphere for too long :-)
No, no sorry :) I meant that I have a template I fill on server with data for Echarts. The data are then embedded in the html. So all is done server side and I serve a self standing html
$ while true; do echo
shuf -i 0-20 -n 1
> /tmp/values.txt; sleep 1; doneShould be
$ while true; do echo
shuf -i 0-20 -n 1
>> /tmp/values.txt; sleep 1; doneNote double > (>>)