nagix / chartjs-plugin-streaming

Chart.js plugin for live streaming data
MIT License
515 stars 130 forks source link

TypeError: Cannot read properties of undefined (reading 'getDatasetMeta') #197

Open adrianblakey opened 3 weeks ago

adrianblakey commented 3 weeks ago

Any ideas what causes this excp?

As you might see, the script opens a websocket, data is sent to the browser about every 10ms as a csv tuple.

Browser console repeatedly says:

chartjs-plugin-streaming.js:250 Uncaught TypeError: Cannot read properties of undefined (reading 'getDatasetMeta') at Va.update$1 [as update] (chartjs-plugin-streaming.js:250:28) at Va.handleEvent (index.umd.ts:50:18) at Object.afterEvent (index.umd.ts:50:18) at d (color.esm.js:97:17) at sn._notify (index.umd.ts:50:18) at sn.notify (index.umd.ts:50:18) at An.notifyPlugins (index.umd.ts:50:18) at An._eventHandler (index.umd.ts:50:18) at An.update (index.umd.ts:50:18) at An.update (chartjs-plugin-streaming.js:795:35)

index.html

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Slot Car Data Logger</title>
    <link rel="stylesheet" href="static/index.css" />
    <link rel="apple-touch-icon" sizes="180x180" href="static/apple-touch-icon.png">
    <link rel="icon" type="image/png" sizes="32x32" href="static/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="static/favicon-16x16.png">
    <link rel="manifest" href="/site.webmanifest">
    <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/luxon@3.4.4/build/global/luxon.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@1.3.1/dist/chartjs-adapter-luxon.umd.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-streaming@2.0.0/dist/chartjs-plugin-streaming.js"></script>
</head>
<body>
    <canvas id="theChart" width="600" height="400"></canvas>
    <script src="static/index.js"></script>
</body>
</html>

index.js

const CHART_COLORS = {
  red: "rgb(255, 99, 132)",
  orange: "rgb(255, 159, 64)",
  yellow: "rgb(255, 205, 86)",
  green: "rgb(75, 192, 192)",
  blue: "rgb(54, 162, 235)",
  thinblue: "rgb(54, 162, 235, 0.5)",
  purple: "rgb(153, 102, 255)",
  grey: "rgb(201, 203, 207)",
};

const NAMED_COLORS = [
  CHART_COLORS.red,
  CHART_COLORS.orange,
  CHART_COLORS.yellow,
  CHART_COLORS.green,
  CHART_COLORS.blue,
  CHART_COLORS.thinblue,
  CHART_COLORS.purple,
  CHART_COLORS.grey,
];

function namedColor(index) {
  return NAMED_COLORS[index % NAMED_COLORS.length];
}

function transparentize(value, opacity) {
  var alpha = opacity === undefined ? 0.5 : 1 - opacity;
  return colorLib(value).alpha(alpha).rgbString();
}

const data = {
  datasets: [
    {
      label: "Track Voltage",
      backgroundColor: CHART_COLORS.red,
      borderColor: CHART_COLORS.red,
      lineTension: 0,
      fill: false,
      data: [],
      yAxisID: "y",
      pointRadius: 0,
      order: 3,
    },
    {
      label: "Controller Voltage",
      backgroundColor: CHART_COLORS.thinblue,
      borderColor: CHART_COLORS.thinblue,
      lineTension: 0,
      fill: true,
      yAxisID: "y",
      data: [],
      pointRadius: 0,
      order: 1,
    },
    {
      label: "Controller Current",
      backgroundColor: CHART_COLORS.orange,
      borderColor: CHART_COLORS.orange,
      lineTension: 0,
      fill: false,
      yAxisID: "y1",
      data: [],
      pointRadius: 0,
      order: 2,
    },
  ],
};

const config = {
  type: "line",
  data: data,
  options: {
    interaction: {
      intersect: false,
      mode: 'index',
    },
    plugins: {
      tooltip: {
        enabled: true,
      },
      title: {
        display: true,
        text: "Data Logger",
      },
      streaming: {
        duration: 2000, 
        refresh: 10,
        frameRate: 30,
        delay: 5,
      },
    },
    scales: {
      x: {
        type: "realtime",
      },
      y: {
        position: "left",
        title: {
          display: true,
          text: "Voltage",
        },
        min: 0,
        max: 15,
      },
      y1: {
        position: "right",
        title: {
          display: true,
          text: "Current",
        },
        min: -15,
        max: 15,
        grid: {
          drawOnChartArea: false, 
        },
      },
    },
  },
};

const theChart = new Chart(document.getElementById("theChart"), config);
var targetUrl = `ws://${location.host}/ws`;
var websocket;
window.addEventListener("load", onLoad);

function onLoad() {
  initializeSocket();
}

function initializeSocket() {
  // console.log("Opening WebSocket connection MicroPython Server...");
  websocket = new WebSocket(targetUrl);
  websocket.onopen = onOpen;
  websocket.onclose = onClose;
  websocket.onmessage = onMessage;
}
function onOpen(event) {
  // console.log("Starting connection to WebSocket server..");
}
function onClose(event) {
  // console.log("Closing connection to server..");
  setTimeout(initializeSocket, 2000);
}
function onMessage(event) {
  let tok = event.data.split(",");
  // tv, cv, ci
  // console.log("Update values", tok[0], tok[1], tok[2]);
  const now = Date.now();
  //console.log(now, ts)
  theChart.data.datasets[0].data.push({
    x: now,
    y: parseFloat(tok[0]),
  });
  theChart.data.datasets[1].data.push({
    x: now,
    y: parseFloat(tok[1]),
  });
  theChart.data.datasets[2].data.push({
    x: now,
    y: parseFloat(tok[2]),
  });
  theChart.update("quiet");
}

function sendMessage(message) {
  websocket.send(message);
}

function updateValues(data) {
  sensorData.unshift(data);
  if (sensorData.length > 20) sensorData.pop();
  sensorValues.value = sensorData.join("\r\n");
}