Wind Direction & Speed Timeline

If time is Time field not a string like in the original example, then xAxis type should be set as time:

let wind;
data.series.map((s) => {
  const time = s.fields.find((f) => f.name === 'Time').values.buffer;
  const value = s.fields.find((f) => f.name === 'Speed').values.buffer;
  const rotate = s.fields.find((f) => f.name === 'Direction').values.buffer;

  /**
  Set Wind from 3 arrays
  */
  wind = time.map((id, index) => {
    return { symbolRotate: rotate[index], value: [time[index], value[index]] };
  });

});

return {
  xAxis: {
    type: 'time'
  },
  yAxis: {
    type: 'value'
  },
  visualMap: {
    orient: 'horizontal',
    left: 'center',
    min: 0,
    max: 10,
    text: ['High', 'Low'],
    dimension: 1,
    inRange: {
      color: ['#65B581', '#FFCE34', '#FD665F']
    }
  },
  series: [
    {
      data: wind,
      type: 'line',
      symbol: 'path://M31 24.7343L21.7917 24.7343V0L9.20826 0L9.20826 24.7343H0L15.5 45L31 24.7343Z',
      symbolSize: 20,
      lineStyle: {
        width: 0.3
      }
    }
  ]
};

@Alvaro_Villa If you have multiple series, you can:

  1. Use the Outer join transformation using the Time Field name to merge them into one;
  2. Rewrite your queries to a single series with both fields;
  3. Rewrite the script to look for fields in all queries and then combine them.

Option 1 is the easiest:

Doesn’t works :frowning:


@Alvaro_Villa What is your Grafana version? I am using 9.1.6.

I’m using the 9.2.1 version

1 Like

@dutarahisu had a similar question on how I was querying the data from InfluxDB.

To query, I am using Flux (instead of InFluxQL).

There are different ways to do this (that might be “better”), but here are my two queries that fetch both the wind gust (windGust) and the wind direction (windDir). For my data needs, finding the mean every 15 minutes was sufficient. I then joined this data together on _time:

windGust = from(bucket: "weather")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "sensor.windgust")
  |> filter(fn: (r) => r["_field"] == "value")
  |> aggregateWindow(every: 15m, fn: mean, createEmpty: false)

windDir = from(bucket: "weather")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "sensor.winddir")
  |> filter(fn: (r) => r["_field"] == "value")
  |> aggregateWindow(every: 15m, fn: mean, createEmpty: false)

join(
  tables: {windGust, windDir},
  on: ["_time"]
)

Which gives me data structured like:

Then to correctly build the data object (series) that Apache ECharts needs, I did the following (irrelevant parts removed for brevity):

const series = data.series.map((s) => {
  const sDataWindDir = s.fields.find((f) => f.name === '_value_windDir').values.buffer;
  const sDataWindGust = s.fields.find((f) => f.name === '_value_windGust').values.buffer;
  const sTime = s.fields.find((f) => f.type === 'time').values.buffer;

  return {
    name: s.name,
    type: 'line',
    symbol: 'path://M31 24.7343L21.7917 24.7343V0L9.20826 0L9.20826 24.7343H0L15.5 45L31 24.7343Z'
    symbolSize: 10,
    data: sTime.map((d, i) => {
      return { value: [d, sDataWindGust[i]], symbolRotate: (sDataWindDir[i]) };
    })
  };
});

There is however a caveat to how I am currently simply finding the “mean” for every 15 minutes and that is when the wind is coming out of the North, the mean is going to tend show South if the wind is varying slightly. Basically because you will get some readings that are slight “West” of North (i.e. 350°, 358°) and some that are slight “East” of North (i.e. 5°, 7°). When you find the mean of these values it is obviously going to be somewhere around 180° - which is inaccurate in this context.

For now I am simply using the “first” value every 15 minutes instead of the “mean”. BUT when I get time, I plan on more accurately calculating the mean for these scenarios. Here is an article that explains the issue in better detail and one way to approach it.

3 Likes

look great - works for me!! is there a way to show both windspeed and wind direction on tooltip?

This works and looks great!

Quick question how do you convert the epoch_time at the bottom of the chart to something human readable?

here is my current setup for those looking for help:
Couple pointers:

  • Format set to Table
  • Under transform perform a join like @ mikhailvolkov says
  • Filter out nulls (see second screenshot)

let wind;
data.series.map((s) => {
  const time = s.fields.find((f) => f.name === 'Time').values.buffer;
  const value = s.fields.find((f) => f.name === 'wind_speed').values.buffer;
  const rotate = s.fields.find((f) => f.name === 'wind_dir').values.buffer;

  /**
  Set Wind from 3 arrays
  */
  wind = time.map((id, index) => {
    return { symbolRotate: rotate[index], value: [time[index], value[index]] };
  });

});

return {
  xAxis: {
    type: 'category'
  },
  yAxis: {
    type: 'value'
  },
  visualMap: {
    orient: 'horizontal',
    left: 'center',
    min: 0,
    max: 10,
    text: ['High', 'Low'],
    dimension: 1,
    inRange: {
      color: ['#65B581', '#FFCE34', '#FD665F']
    }
  },
  series: [
    {
      data: wind,
      type: 'line',
      symbol: 'path://M31 24.7343L21.7917 24.7343V0L9.20826 0L9.20826 24.7343H0L15.5 45L31 24.7343Z',
      symbolSize: 20,
      lineStyle: {
        width: 0.3
      }
    }
  ]
};
1 Like

Set type for xAxis as time.

Hello,
I followed all the directions to create a beautiful diagram as above. Everything was working fine until I updated grafana to V10.0.1 and echarts plugin version 4.5.0. Do you have an idea to remove the error “time is undefined” Thanks


Please check requirements for that plugin

Requirements

  • Grafana 8.5+, Grafana 9.0+ is required.

Apache ECharts plugin for Grafana | Grafana Labs.

@Ratamuse Grafana 10 introduced breaking changes to get data from a data source using values.
Just remove the .buffer and you will be fine.

Grafana 10 is fully supported, I will update README to make it clear.

1 Like

@yosiasz We updated README about support Grafana 10 in the GitHub repository:

I will submit a new version soon to update in the Grafana Catalog.

1 Like

Remember this @mikhailvolkov

That buffer thing always seemed so odd

https://localhost:3000/t/use-of-datasource-in-apache-echart/73538/9

1 Like

Hello, it’s working well now, thanks a lot!

Greetings!
In this example, when direction is 90, shouldn’t the arrow indicate easterly wind, e.g. wind blowing from the east?
And the first sample data, 45 degrees, shouldn’t that be rougly NE or NNE wind? Why is it pointing to the SE direction though?
How can symbolrotate be used to use traditional wind dir arrow directions?

1 Like

@squubiduu That’s a beauty of the Apache ECharts, you can display data the way you wanted without any restrictions.

You can add your own logic to flip, update direction values in the function after reading data from the data source.

Thanks for everybody in this thread. After initial headbanging it was pretty easy to create a nice wind speed and direction graph Wind Speed and Direction with Grafana ECCharts plugin ¡ GitHub

2 Likes

@tkurki Thank you for sharing.

There is definitely a learning curve. The result is well worth the effort.