Search code examples
javascriptd3.jswebsocketautobahn

d3js chart update triggered on websocket message


Running an autobahn websocket server in Python and picking up json updates in the html frontend. The value (in this case "temp") is being displayed as a number with innerHTML when message arrive and that part works fine.

We also got a dial chart (d3js) but the update is initiated by the setInterval function at the end of the code which is far from ideal. How can I make the gauge update 'onmessage' through the websocket?

enter image description here

<script type="text/javascript">

//---the websocket part--
var sock = null;
var displaynumber = null;
var tempdata = null;

window.onload = function () {
  var wsuri;
  displaynumber = document.getElementById('disp');

  if (window.location.protocol === "file:") {
    wsuri = "ws://...:9000";
  } else {
    wsuri = "ws://" + window.location.hostname + ":9000";
  }

  //set up a new websocket
  if ("WebSocket" in window) {
      sock = new WebSocket(wsuri);
  } else if ("MozWebSocket" in window) {
      sock = new MozWebSocket(wsuri);
  } else {
      disp("Browser does not support WebSocket!");
               window.location = "http://autobahn.ws/unsupportedbrowser";
  }

  if (sock) {
    //sock.onopen = function() {};

    sock.onclose = function(e) {
      sock = null;
    };

    sock.onmessage = function(e) {
      // e.data will be sent as a string and need to be converted to object
      var jsondata = JSON.parse(e.data);
      tempdata = jsondata.temp;
      disp(tempdata + " C");
    };
  }

  function disp(m) {
    displaynumber.innerHTML = m;
  }


  //----This is the dial chart part

  dialChart();

  function dialChart() {
    var powerGauge = gauge('#power-gauge', {
      size: 300,
      clipWidth: 300,
      clipHeight: 300,
      ringWidth: 60,
      minValue: 0,
      maxValue: 100,
      transitionMs: 1000,
    });

    powerGauge.render();

    function updateReadings() {
      powerGauge.update(tempdata);
    }

    updateReadings();
    setInterval(function() {
      updateReadings();
    }, 2 * 1000);
  }
}

</script>

Solution

  • At the end of the definition of dialChart, add return powerGauge. Then when you call dialChart();, save the result to a variable. Then, instead of writing to tempdata in the socket callback, call powerGaugeVariable.update(jsondata.temp).