0

I want to plot my temperature readings of my DIY thermostat and the heater-state using Chart.js. The heater-state is 0 or 1, but I saved it in a minimal representation: I have values only, when it comes on/off. The heating times are never equal to the measurement times, but in between.

I want to plot time-data on the same time x-axis. From at least 20 examples, questions here and other resources I collected this Fiddle, which is my best guess. However, I can't reasonably plot both time axes and their data. If I reduce it to numerical data on the x axis in a very much simplified example, I get the smaller dataset plotted on the first few x-values of the latter one.

The js code is:

var options = {
  type: 'line',
  data: {
    labels: ["2018-12-07 08:45:17", 
    "2018-12-07 09:30:17", "2018-12-07 10:15:16", 
    "2018-12-07 11:00:17", "2018-12-07 14:45:16"],
    datasets: [
        {
          label: '1st line',
          data: [12, 19, 7, 9, 10, 8],
        },  
            {
          steppedLine: 'before',
          xAxisID: 'x-axis-2',
          label: '2nd line',
          data: [                       
          {
            x: "2018-12-07 09:15:47",
            y: 3
          }, {
            x: "2018-12-07 10:55:25",
            y: 5
          }, {
            x: "2018-12-07 13:05:00",
            y: 3
          }],
        }
     ]
  },
  options: {
    scales: {
      xAxes: [{}, {
        id: 'x-axis-2',
        type: 'linear',
        position: 'bottom',
        //display: false,
      }],
    }
  }
}

var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
mike
  • 791
  • 11
  • 26

2 Answers2

2

First, you could use a unique xAxis and define it as a time cartesian axis.

xAxes: [{
  type: 'time',
  time: {
    unit: 'second'
  }
}]

Also you shouldn't provide data.labels but rather define each data point using an object containing x and y properties.

var options = {
  type: 'line',
  data: {
    datasets: [{
        label: '1st line',
        data: [{
            x: "2018-12-07 08:45:17",
            y: 12
          },
          {
            x: "2018-12-07 09:30:17",
            y: 19
          },
          {
            x: "2018-12-07 10:15:16",
            y: 7
          },
          {
            x: "2018-12-07 11:00:17",
            y: 9
          },
          {
            x: "2018-12-07 14:45:16",
            y: 10
          }
        ]
      },
      {
        label: '2nd line',
        steppedLine: 'before',
        data: [{
            x: "2018-12-07 09:15:47",
            y: 3
          },
          {
            x: "2018-12-07 10:55:25",
            y: 5
          },
          {
            x: "2018-12-07 13:05:00",
            y: 3
          }
        ],
        backgroundColor: 'lightgreen'
      }
    ]
  },
  options: {
    scales: {
      xAxes: [{
        type: 'time',
        time: {
          unit: 'second'
        }
      }]
    }
  }
}

var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="chartJSContainer" height="90"></canvas>
uminder
  • 23,831
  • 5
  • 37
  • 72
  • For someone new to chartjs, I didn't even realize that it could draw an axis with ticks without providing the labels. Wish the docs were more clear when to provide your own labels and when not to. Thanks! – Matt Jones May 02 '23 at 01:16
0

I was finally able to figure out the problem which was the datastructure of the javaScript object. It requires this structure [{ "x": 1, "y":1}, {"x":2, "y":3} ] where in particular the x and y are the object properties x and y for each entry, rather than once and for all (which always made a lot more sense to me). But I can send the data without this extra labels and convert them on the fly with javascript like so:

datasets: [
{
  label: 'Temperature',
  data: response.temperature.x.map((x, i) => ({ x, y: response.temperature.y[i] })),
},
{
  label: 'Room 2 Temperature',
  data: response.temp2.x.map((x, i) => ({ x, y: response.temp2.y[i] })),
},
] // datasets
mike
  • 791
  • 11
  • 26