Call all data from a bucket in thinger HTML bucket?

Hi team

When creating an HTML widget in thinger.io, you can select only 1 value/property from the bucket or device:
Capture

Is it possible to call all values from a bucket/device in the HTML widget?

Thanks!
Gus

Hi @gus,

this is indeed a required feature for html widgets, so later you can use the value as {{value.ts}} {{value.temperature}}, {{value.count}}. Will try to include it on the upcoming release.

Hi @alvarolb ,

Can we achieve this function through the developer mode in the dashboard settings, or it has not been implemented yet?

Cheers,
Hans

Hi @Hans_Wu , this feature has been included in 3.1.0 version.

Awesome! Now I can make it in the plain text such as

<p>A:{{value.v1}} B:{{value.v2}}</p>

But it seems still don’t work in the script like:

<div id="chart_div" style="width: 900px; height: 500px;"></div>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
  google.charts.load('current', {'packages':['corechart']});
  google.charts.setOnLoadCallback(drawChart);

  function drawChart() {
    var data = google.visualization.arrayToDataTable([
      ['Age', 'Weight'],
      [ {{value.v1}},  {{value.v2}}]
    ]);

    var options = {
      title: 'Age vs. Weight comparison',
      hAxis: {title: 'Age', minValue: 0, maxValue: 15},
      vAxis: {title: 'Weight', minValue: 0, maxValue: 15},
      legend: 'none'
    };

    var chart = new google.visualization.ScatterChart(document.getElementById('chart_div'));

    chart.draw(data, options);
  }
</script>

Is there any way to read the value from a script as we want to show the data in a different format?

Hi, in Javascript it is possible to define a function to receive updates, as {{}} can only be used on HTML. The function is the following, and can be placed in your script (but it does not scale to multiple html widgets):

    function onUpdate(ts, value) {
      //ts is the timestamp
      // value is a json with your variable, i.e., {'v1':3, 'v2':1} 
    }

For your use case, it is possible to get it working, but it is a bit more tricky, as google charts libraries will be lazy loaded with the widget load, and not page load. So, it is a bit tricky, but here it is a working example (with lat and lon fields):

<div id="chart_div1" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0;">
  <script>
    function loadLibraries() {
      return new Promise((resolve, reject) => {
        let dependencies = [`https://www.gstatic.com/charts/loader.js`];

        let resolved = 0;

        dependencies.forEach(function (src) {
          let script = document.createElement("script");
          script.src = src;
          script.async = false;

          // Resolve the promise once the script is loaded
          script.addEventListener("load", () => {
            if (++resolved === dependencies.length) {
              resolve(resolved);
            }
          });

          // Catch any errors while loading the script
          script.addEventListener("error", () => {
            reject(new Error(`${src} failed to load.`));
          });

          document.head.appendChild(script);
        });
      });
    }

    var chart, lastTs, lastValue;

    function onUpdate(ts, value) {
      lastTs = ts;
      lastValue = value;
      if (chart) updateChart();
    }

    function updateChart() {
      var data = google.visualization.arrayToDataTable([
        ["Age", "Weight"],
        [lastValue.lat, lastValue.lon],
      ]);

      var options = {
        title: "Age vs. Weight comparison",
        hAxis: { title: "Age", minValue: 0, maxValue: 15 },
        vAxis: { title: "Weight", minValue: 0, maxValue: 15 },
        legend: "none",
      };

      chart.draw(data, options);
    }

    function initChart() {
      chart = new google.visualization.ScatterChart(document.getElementById("chart_div1"));
      if (lastValue) updateChart();
    }

    loadLibraries()
      .then((result) => {
        google.charts.load("current", { packages: ["corechart"] });
        google.charts.setOnLoadCallback(initChart);
      })
      .catch((error) => {
        console.error(error);
      });
  </script>
</div>

This is the result:

Notice that this approach will fail if you want to add more than one chart of this type in the same dash, as the inner javascript defines some global variables in the page. Did you considered the Apex Charts?

Bests!

Hi,

Thank you very much, this is a very good example for my project.
I only need to use one HTML widget at the moment. As I need to have a scatter plot to demonstrate my data, which is unavailable in the Apex charts, this is the best solution for now. But I am still curious about why this won’t work if I have multiple HTML widgets? Is it because of multi-threading that the bucket cannot be called from two threads at the same time?
The sample code works on my dashboard, but I think it does not always read the correct values. When I implement it directly on my dashboard, the widget shows the scatter plot with a warning:
Data column(s) for axis #0 cannot be of type string in google chart dashboard
I assume that it may due to the data type, so I modify the updateChart function to
[parseFloat(lastValue.v1), parseFloat(lastValue.v2)]
In this way, the warning disappears, but my scatter sometimes disappear from the chart as well (it was there when I refresh the page but disappear after a while). So the widget may read some unexpected values (string type) from the bucket or somewhere else. Do you know the reason for this issue and how I can fix it? (It does not happen when I read data directly from the device)

Thank you in adnvace.

Hi!

If you need to use parseFloat with your fields is that you are storing the values as strings. You can check it by exporting your bucket as CSV and check if numeric fields are quoted. Please, review your integration, specially how do you encode your numeric fields, as this will also prevent using aggregation.

If the chart is disappearing it may be related with onUpdate method calling chart redraw. I have not tested it extensively, so It is possible those charts require a different call for updating the data.

In the other side Apex charts supports Scatter but by default it is plotting time series data. Will check how we can change it for defining a different X axis.

That will be much helpful. Thank you very much.