Almost all the features of the Yoctopuce API are present in the LabVIEW library, this represents more than 2000 possible distinct functions through more than 80 classes. However, there is only one VI per class, so how could we cram an average of 25 calls per VI? This week, we are going to explain to you in more details the concept of proxy objects for the LabVIEW Yoctopuce API.
The Yoctopuce VIs
We designed the Yoctopuce VIs to provide immediate access to the properties that we deemed most important for each class. For example, you can read a temperature sensor in a straightforward way:
The simplest way to read a temperature sensor with the LabVIEW library
You only have to:
- Initialize the Yoctopuce API with the RegisterHub VI
- Read the temperature with the Temperature VI
- Free the API with the FreeAPI VI
Here, we directly used the currentValue output, but how can we access more advanced features? For example, how can we ask the temperature sensor which are the minimal and maximal values that it observed? This was planned: set the "create ref" input to TRUE and you obtain on the "optional ref" output a reference to the Proxy object corresponding to the sensor. This Proxy object is used to manage the sensor as a background task and to allow access to all the methods and properties pertaining to the Temperature sensor, including get_highestValue() and get_lowestValue().
Using the TemperatureProxy object to know the min and max values
However, it is important to remember to close the reference when you don't need it anymore. Note that "closing the reference" does only what's written on the label: that is, it signals to LabVEIW that we don't need to interact with this Proxy object anymore, but the object continues to exist and lives its own life as a background task.
How does it work?
If you look at the source code of the Temperature VI, you can easily understand the principle. When you use the Yoctopuce library Temperature VI, there is a call to the YoctoProxyManager static class. This call is used to obtain a reference on the Proxy object corresponding to the name given as parameter. Without a name, the returned object corresponds to the first sensor found. Note that if no sensor can be found, you obtain a valid reference but pointing to a lambda sensor which states that it is "Off line".
Source of the Temperature VI
This reference on the Proxy object is used to retrieve the value of all the properties directly interfaced by the VI. When all the necessary properties are managed, the parameter create ref is either set to FALSE (default value) and the reference is closed, or set to TRUE and the reference is returned directly via the "optional ref" output, and it's up to you to make good use of it.
A less trivial example
This mechanism may seem luxury on classes as simple as Temperature, but it is truly essential on more complex classes. The Display class is the perfect example. To display a simple "Hello" on a display, multiple calls are required.
Displaying 'Hello' top-left of a Yoctopuce display
- Use the Display VI to obtain a reference on the YDisplayProxy object
- Use this reference for a call to resetAll, erasing the whole display
- Still with this reference, call get_displayLayer(1) to obtain another reference, of type YDisplayLayerProxy, on layer #1 of the display
- Then use this reference on layer #1 to display the "Hello" text in position 0,0 with a TOP/LEFT alignment. The alignment constant is provided by the "YDisplayLayerProxy" class
- Finally, the references are closed and the API freed
If your use of Yoctopuce modules is limited to reading a sensor or commuting a relay, the provided VIs are fully sufficient. However, if you need to manage somewhat complex behaviors, you'll need to use these references on Proxy objects. But as we just saw it, it's far from impossible. Finally, here are a few points you should keep in mind:
- By convention, the proxy API properties are managed with a cache by the library and you can call them as often as you wish, without penalizing the execution time
- Most of the proxy API methods require explicit communications with the module and must be called wisely: the more communications, the slower you code
- All the references must be closed, otherwise LabVIEW will soon run out of resources
Finally, note that the couple of examples provided here don't perform error handling, so don't copy them as is in a production application.