New data logger and graphs

New data logger and graphs

courtesy of www.sxc.huNot long ago, tracing a dynamic graph with the values of a Yoctopuce sensor required you to have a database to store the history. Indeed, retrieving the data from the data logger was clearly too slow for an interactive application. It so happens that the data logger component of Yoctopuce products has been greatly improved, at both the API and firmware levels. Retrieving data from the data logger is now done in a flash. Demo with a C# example.


To show you how user-friendly the data logger has become, we are going to write together a short C# application that traces the data history of a Yoctopuce sensor, then updates the graph in real time. The application is quite interesting because it takes advantage of a number of features that appeared with the new API.

The YSensor class

YSensor is a new class, parent to all the Yoctopuce sensors. No need to write code specific to each sensor anymore: we can do with generic code as long as we keep to basic functions common to all sensors, such as get_currentValue, get_unit, and so on.

loadMore

Loading the data from the data logger is performed iteratively thanks to loadMore. It returns the percentage of data actually loaded and thus enables us to display a nice progression bar while loading the data.

Timed Report

We now have a new type of callback: TimedReport. When defined, this callback calls at regular intervals a function of your choice with the value of the sensor you are interested in. Very convenient to automatically update the graph.

It so happens that the .NET framework provided a Chart class, enabling you to relatively easily trace very correct graphs, with zoom management and everything. So we only need to retrieve the data from the data logger to transfer them to the .NET object. Let's have a closer look at how to do this.

Sensor dynamic inventory

In our application, we want to be able to chose between all the connected sensors. To do so, we need to build a sensor inventory which we can present to the user in a comboBox. Obviously, we want this comboBox to update itself when sensors are connected or disconnected. USB is plug-and-play, let's take advantage of this :-)

So we set up two callbacks: the first one called when a module is connected, and the second one called as soon as a module is disconnected.

YAPI.RegisterDeviceArrivalCallback(deviceArrival);
YAPI.RegisterDeviceRemovalCallback(deviceRemoval);


Note that these callbacks are in fact called only when YAPI.UpdateDeviceList is executed, so we must call this function from time to time, with the help of a timer for instance.
Each time deviceArrival is called, we enumerate all the connected sensors, and we add the missing ones in the comboBox.

public void deviceArrival(YModule m)
  { YSensor s = YSensor.FirstSensor();
    while (s != null)
      { if (!comboBox1.Items.Contains(s))
          comboBox1.Items.Add(s);
        s = s.nextSensor();
      }
  }


Each time deviceRemoval is called, we check that each sensor stored in the comboBox is actually onLine, if not we remove it from the list.

public void deviceRemoval(YModule m)
   { for (int i = comboBox1.Items.Count - 1; i >= 0; i--)
       if (!((YSensor)comboBox1.Items[i]).isOnline())
           comboBox1.Items.RemoveAt(i);
   }


This is it for dynamic inventory.

Extracting the data from the data logger

Extracting the data is a three steps process:

  1. We ask the API to load the data from the data logger. To do so, we use the loadMore function of the DataSet returned by the get_recordedData function of the sensor. We call this loadMore function in a loop, it very conveniently returns the percentage of data already loaded, enabling us to update a progression bar.
  2. At this point, all the data of the data logger have been transferred from the module to the computer, but they are still somewhere in the shallows of the API. We then use the get_measures() function to transfer them into a C# list.
  3. Finally, we only need to transmit these data to the graph.

  YSensor s= getSelectedSensor();
  YDataSet data = s.get_recordedData(0, 0);
  //data loading
  int progress = data.loadMore();
  while (progress < 100)
    { progressBar.Value = progress;
      Application.DoEvents();
      progress = data.loadMore();
    }
  //transfer into an array
  List<YMeasure> alldata = data.get_measures();
  // sending the data to the graph
  for (int i = 0; i < alldata.Count; i++)
    { DateTime t = UnixTimeStampToDateTime(alldata[i].get_endTimeUTC())
      chart1.Series[0].Points.AddXY( t, alldata[i].get_averageValue());
    }
  // displaying the units
  chart1.ChartAreas[0].AxisY.Title = s.get_unit();


Real time updating

To update the graph in real time, we use the brand new callback TimedReport. This callback, which you can configure independently for each sensor, enables you to call the function of your choice with the value of the sensor.

  YSensor s= getSelectedSensor();
  s.set_reportFrequency("3/s"); // 3 times per second
  s.registerTimedReportCallback(newSensorValue);



Beware, the TimeReport callback is called only when YAPI.Sleep or YAPI.HandeEvents is executed. So you must call one of these functions from time to time. Using a timer is ideal for this.

The callback, meanwhile, is really simple. It only adds to the graph the measure received as a parameter.

public void newSensorValue(YFunction f,  YMeasure m)
   {  DateTime t  = UnixTimeStampToDateTime(m.get_endTimeUTC());
      chart1.Series[0].Points.AddXY(t , m.get_averageValue());
   }



Here we are, we discussed the Yoctopuce code enabling you to trace a graph of a sensor history thanks to the data in the data logger and to keep this graph constantly up to date. The whole project is available here. It will be part of the C# library examples at the next release.

A graph tracing application, written in no time
A graph tracing application, written in no time


Naturally, for this application to work, you need your Yoctopuce library and firmware to be up-to-date. They are still in beta-test, but you can download them here.




1 - edeon Monday,august 24,2015 10H39

Does is works with Yocto-Meteo?
In the middle of the application window message appears: "Please connect the temperature recorder."
Firmware and VirtualHub are up to date.
Log:
2015-08-24 12:32:41 : Application start
2015-08-24 12:32:42 : Device arrival (VIRTHUB0-6a59665f56)
2015-08-24 12:32:42 : Device arrival (METEOMK1-312E7)

2 - mvuilleu (Yocto-Team)Monday,august 24,2015 12H15

The .NET examples by default connect directly to the local USB port to access the sensor. You should therefore not start the VirtualHub, or the USB ports will be marked as busy.

If you want to change the examples to connect through the VirtualHub instead of accessing USB directly, you should edit the code replace the line
    YAPI.RegisterHub("usb");
by
    YAPI.RegisterHub("127.0.0.1");

3 - edeon Monday,august 24,2015 12H41

I tried without starting the VirtualHub also, but the message is the same: "Please connect a temperature recorder.". Maybe OS is responsible: Windows 7 ?

4 - martinm (Yocto-Team)Monday,august 24,2015 14H31

I suspect the version linked in that article does not have proper support for the Yocto-Meteo, just use the one in the C# library, I just checked, it works.

Yoctopuce, get your stuff connected.