0

I made a chart using ChartJS that would fetch data from a server being hosted on a microcontroller connected to a few devices streaming data into a CSV every seconds. The chart works fine and shows the correct data except that it doesn't update/animate the graph unless you refreshed the page. I'd like to make it so that the chart pushes and animates the new data without the refreshing.

I've found a couple of answers but none would work for me. I found this video as well

drawChart();
// setup 
async function drawChart() {
  const datapoints = await getData();

  const data = {
    labels: datapoints.labels,
    datasets: [{
        label: 'Solar Voltage',
        data: datapoints.solar.voltage,
        borderColor: [
          'rgba(255, 159, 28, 1)'
        ],
        tension: 0.15,
        yAxisID: 'y'
      },
      {
        label: 'Solar Current',
        data: datapoints.solar.current,
        borderColor: [
          'rgba(254, 215, 102, 1)'
        ],
        tension: 0.15,
        yAxisID: 'y1'
      }
    ]
  };

  Chart.defaults.font.family = "Verdana";

  // config 
  const config = {
    type: 'line',
    data,
    options: {
      scales: {
        y: {
          beginAtZero: true,
          display: true,
          position: 'left',

          title: {
            display: true,
            text: 'voltage'
          }
        },
        y1: {
          beginAtZero: true,
          display: true,
          position: 'right',

          grid: {
            drawOnChartArea: false
          },

          title: {
            display: true,
            text: 'current'
          }
        }
      }
    }
  };

  // render init block
  const myChart = new Chart(
    document.getElementById('solar-graph'),
    config
  );
}

async function getData() {
  //arrays to store data
  const labels = [];
  const solar = {
    voltage: [],
    current: []
  };
  const battery = {
    voltage: []
  };

  //fetch csv
  const url = '/data';
  const response = await fetch(url, {
    'content-type': 'text/csv;charset=UTF-8'
  });
  const tabledata = await response.text();

  //parse csv
  //split by row
  const table = tabledata.split('\n').slice(1);

  //split by column
  table.forEach(row => {
    const column = row.split(',');
    labels.push(column[1]);

    solar.voltage.push(column[2]);
    solar.current.push(column[3]);

    battery.voltage.push(column[4]);
  });

  return {
    labels,
    solar,
    battery
  };
}

edit: i fixed it

updateChart();

let labels = [];

let solar = {
    voltage: [],
    current: []
};

let battery = {
    voltage: []
};

//push new values every 1.5 seconds
function updateChart() {
    setInterval(getData, 1500);
}

async function getData() {
    //fetch csv from url
    const url = '/data';
    fetch(url, {
        'content-type': 'text/csv;charset=UTF-8'
    })
    .then(data => data.text(), error => console.warn("Failed to fetch data"))
    .then(tabledata => {
        //split by row
        const table = tabledata.split('\n').slice(1);

        //get last row
        const row = table[table.length - 1].split(',');

        //display 30 data points on the graph at anytime
        if (myChart.data.labels.length > 30) {
            myChart.data.labels.shift();
            myChart.data.datasets[0].data.shift();
            myChart.data.datasets[1].data.shift();
        }
        //update chart
        myChart.data.labels.push(row[1]);
        myChart.data.datasets[0].data.push(row[2]);
        myChart.data.datasets[1].data.push(row[3]);

        //update array
        labels.push(row[1]);
        solar.voltage.push(row[2]);
        solar.current.push(row[3]);
        battery.voltage.push(row[4]);

        myChart.update();
Andy
  • 1
  • 1

1 Answers1

0

Whenever you change the data, you need to update your chart manually

myChart.update()

Are you watched this video you mentioned in your question? Because at 14:12 he also wrote myChart.update()

bill.gates
  • 14,145
  • 3
  • 19
  • 47
  • I did try both of the links I mentioned. Sorry I should've also added that I encountered the same errors (Error: Canvas is already in use. Chart with ID '0' must be destroyed before the canvas can be reused.) in both of the examples. – Andy May 01 '22 at 22:13