Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Trying to use pusher.com to update my highchart spline instead of database polling

Posted on 2013-05-10
5
Medium Priority
?
1,185 Views
Last Modified: 2013-05-12
I have a highchart spline that updates every second to show the incoming call rate per second. So naturally its polling my db each second and returning the amount of calls that have come in during the past second. Not that great. Bit of lag, missing calls, not too great.

function in highchart currently looks like this:
function requestData() { 
$.ajax({ 
    url: 'assets/db/incoming_callrate.php', 
    success: function(point) { 
        var series = chart.series[0], 
            shift = series.data.length > 20; // shift if the series is longer than 20

        // add the point 
        chart.series[0].addPoint(point, true, shift); 

        // call it again after one second 
        setTimeout(requestData, 1000); 
    }, 
    cache: false 
}); 

Open in new window

in my page that the chart resides I am currently using pusher to update what caller number I'm on and to increment a progress bar and trigger a datatable (read: works awesome)

Part of that is below:
channel.bind('newcall', function(data) { 
    if (data['currentcaller']){ 
     document.getElementById("incoming_callers").innerHTML = data['currentcaller']; 
     document.getElementById("bar9").setAttribute('title', data['currentpercent']); 
     var percent = $('#bar9').attr('title'); 
$('#bar9').animate({width: percent},1000);

Open in new window

So in my case if I could somehow trigger my chart each second with the total amount of calls that have occurred in the past second that would be great. Random thoughts were:

I was guessing I need to establish a new variable something like: var callrate = 0;

Then each time pusher sends a notice of a call, increment the call rate up: ++callrate;

and magically somehow: once a second goes by, trigger a function for the chart to update with the total amount of calls that have occurred in the past second and reset the callrate variable to zero for the next second.

Any idea on above?

My database request returns the x and y axis: x being the time() *1000 and y being the amount of callers in one second.
0
Comment
Question by:tjyoung
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
5 Comments
 
LVL 25

Expert Comment

by:clockwatcher
ID: 39158646
Unless you need data about every single call and if you're going to be updating your chart every second rather than live anyway, it seems like it would make more sense to continue with your call/sec rate.  Use a server process to push the call/sec data to pusher app
    while True:
        data = [time.time() * 1000, randint(0,100) ]  # replace with your db call
        print data
        p['my-ee-app'].trigger('chart-event', data)
        time.sleep(1)

Open in new window

and instead of having your clients poll for it, have them subscribe to that event.  Then you really don't have to change much of anything-- just replace your ajax call with a pusher event.  It should be a lot more efficient than having your client poll.
        channel.bind('chart-event', function(data) {
                var series = chart.series[0];
                shift = series.data.length > 20; // shift if the series is longer than 20
                chart.series[0].addPoint(data, true, shift);
        });

Open in new window



I posted a sample at  http://mostlywrong.info/ee.htm

Full client code
<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>

		<script src="http://js.pusher.com/2.0/pusher.min.js"></script>

		<script type="text/javascript">
var pusher = new Pusher('675505d46e4e94515943');
var channel = pusher.subscribe('my-ee-app');

$(function () {

        var chart = new Highcharts.Chart({
            chart: {
                type: 'spline',
		renderTo: 'container'

            },
            title: {
                text: 'Incoming Calls'
            },
            subtitle: {
                text: 'EE Pusher Test'
            },
            xAxis: {
                type: 'datetime',
		tickPixelInterval: 150,
		maxZoom: 20 * 1000

            },
            yAxis: {
                title: {
                    text: 'Call rate'
                },
                min: 0,
		max: 100,
                minorGridLineWidth: 0,
                gridLineWidth: 0,
            },
            tooltip: {
                valueSuffix: ' calls/sec'
            },
            plotOptions: {
                spline: {
                    lineWidth: 4
                }
            },
            series: [{
                name: 'Call Center',
		data: []
                } ]
            ,
            navigation: {
                menuItemStyle: {
                    fontSize: '10px'
                }
            }
        });

        channel.bind('chart-event', function(data) {
                var series = chart.series[0];
                shift = series.data.length > 20; // shift if the series is longer than 20
                chart.series[0].addPoint(data, true, shift);
        });

    });
    

		</script>
	</head>
	<body>
<script src="./js/highcharts.js"></script>
<script src="./js/modules/exporting.js"></script>

<div id="container" style="min-width: 400px; height: 400px; margin: 0 auto"></div>

	</body>
</html>

Open in new window


Full Server
import ConfigParser
import pusher
import time
from random import randint

def main():
    config = ConfigParser.ConfigParser()
    config.readfp(file('config.ini','r'))
    p = pusher.Pusher(app_id=config.get('pusher','app_id'),
                      key=config.get('pusher','key'),
                      secret=config.get('pusher','secret'))
    while True:
        data = [time.time() * 1000, randint(0,100) ] # replace with db query
        print data
        p['my-ee-app'].trigger('chart-event', data)
        time.sleep(1)

if __name__ == '__main__':
    main()

Open in new window

0
 
LVL 1

Author Comment

by:tjyoung
ID: 39158692
This appears to  be brilliant.. so brilliant I dont have a clue about the server part. Where does that go?
Excited at the solution, but dumbfounded at the server part...
0
 
LVL 1

Author Comment

by:tjyoung
ID: 39158742
if i understand you right your saying do the db query and send the result each second to pusher to send out.
that sound right?
wouldnt be able to show the server version as php by chance would you?
0
 
LVL 25

Accepted Solution

by:
clockwatcher earned 2000 total points
ID: 39158823
Here's a php version:
<?php

include './pusher-php-server-master/lib/Pusher.php';

$app_id = 'APP_ID';
$app_key = '675505d46e4e94515943';
$app_secret = 'APP_SECRET_KEY';

$pusher = new Pusher($app_key, $app_secret, $app_id);

while (1) {

        $time_stamp = time() * 1000;
        $calls_per_sec = rand(1,100); // replace with your db query
        $pusher->trigger('my-ee-app', 'chart-event', array($time_stamp, $calls_per_sec));
        sleep(1);
}

?>

Open in new window


The pusher php library is downloadable at https://github.com/pusher/pusher-php-server

You'd need to hook in your database code and would want to run that under php's command line interface (php-cli) on your server-- probably in a supervisord managed process so that it would restart if it goes down.
0
 
LVL 1

Author Closing Comment

by:tjyoung
ID: 39158857
Love it
Many thanks!
0

Featured Post

The top UI technologies you need to be aware of

An important part of the job as a front-end developer is to stay up to date and in contact with new tools, trends and workflows. That’s why you cannot miss this upcoming webinar to explore the latest trends in UI technologies!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Knockoutjs (Knockout) is a JavaScript framework (Model View ViewModel or MVVM framework).   The main ideology behind Knockout is to control from JavaScript how a page looks whilst creating an engaging user experience in the least …
Introduction JSON is an acronym for JavaScript Object Notation.  It is a text-string data transport mechanism, capable of representing simple or complex data structures in a consistent and easy-to-read manner.  Similar in concept to XML, but more e…
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
Suggested Courses

721 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question