Rechercher dans ce blog

Affichage des articles dont le libellé est yocto-meteo. Afficher tous les articles
Affichage des articles dont le libellé est yocto-meteo. Afficher tous les articles

dimanche 29 avril 2012

8. Yocto-common module

The purpose of Yocto-common is to manage all the objects that can contain a VirtualHUB but will not contain the communication layer (that will be managed in the yocto-standalone module).

UML diagram

The diagram is quite straightforward:



  • All the objects that can be accessed through an URL are YoctoObject. They have all a common interface to:
    • get the name
    • get the ProductID
    • get the serial number
    • get the parent hub
    • refresh the object in an immediate or asynchronous way
  • The YoctoHub object has to provide all the devices associated
  • The YoctoMeteo and YoctoColor need a function to return their values

YoctoObjectImpl

YoctoObjectImpl is an abstract class used by all the yocto-devices, most of the functions are getters and setters except the refresh functions. 

69       public void refresh() { 
70           YoctoMap map = template.query(relativePath); 
71           internalRefresh(map); 
72       } 
73    
74       private void internalRefresh(YoctoMap map) { 
75           YoctoMap module = map.getMap("module"); 
76           logicalName = module.getString("logicalName"); 
77           String newSerialNumber = module.getString("serialNumber"); 
78           if (serialNumber == null || serialNumber.equals("")) 
79               serialNumber = newSerialNumber; 
80           else if (!serialNumber.equals(newSerialNumber)) 
81               throw new IllegalStateException("Internal error"); 
82    
83           refreshObject(map); 
84       } 
85    
86       protected abstract void refreshObject(YoctoMap map);


  1. The refresh function basically calls a template with a relative path which depends on the object:
    • the hub will always have a relative path: /api.json
    • other yoctopuce devices will have the more complex path: /by-serial/<serial>/api.json
  2. The template returns an object of type YoctoMap that provides API to access json parsed objects.
  3. When this is done, ObjImpl will fill the parameters common to all the objects and delegate to children the rest of the operation.
Now that the synchronous refresh has been described, let's try to describe the asynchronous version:
 
56       public void refresh(final YoctoCallback<Void> callback) { 
57           template.aSyncQuery(relativePath, new YoctoCallback<YoctoMap>() { 
58               public void onSuccess(YoctoMap result) { 
59                   internalRefresh(result); 
60                   callback.onSuccess(null); 
61               } 
62    
63               public void onError(Throwable t) { 
64                   callback.onError(t); 
65               } 
66           }); 
67       }

For the asynchronous refresh, the aSyncQuery from the template is called and a callback will be called when the result has been fetched. When fetched, the first thing to do it to refresh the object and then to call the callback function provided to the function.

YoctoTemplate

The YoctoTemplate is an interface that is implemented in other modules but here is the source code of this interface:

public interface YoctoTemplate { 
24       public YoctoMap query(String relativePath); 
25    
26       public void aSyncQuery(String relativePath, YoctoCallback<YoctoMap> listener); 
27    
28   }

Difficult to be simpler!

YoctoMap

We have seen that the YoctoMap is the object returned by the YoctoTemplate, but what is it? It is a interface that helps us to access the JSON result in a xPath approach:


public interface YoctoMap { 
22    
23       public YoctoMap getMap(String name); 
24    
25       public String getString(String name); 
26    
27       public int getInt(String name); 
28    
29       public YoctoList getList(String name); 
30   }

For example, to access an object, the code: map.getMap("module").getString("logicalName") will allow getting the logicalName of a device.

There is nothing particularly complex in this module, the code consists mainly of implementing the different devices provided by yoctopuce.

7. Yoctopuce

Now, we can start the analysis part of Yoctopuce devices. These devices are low cost devices that you plug on your USB port.  For the purpose of this demo, I bought this device: https://www.yoctopuce.com/EN/products/yocto-meteo

If you have a native interface, you can directly use a library but in my case, I do not. So, I will use a tool called VirtualHub which provides a simple REST interface.

When the yocto-meteo is plugged and VirtualHub is running. You should be able to go on http://127.0.0.1:4444 and see this page:





This means that the devices and VirtualHub are working properly. We can see there are two devices:


  • VirtualHub: the device to which the different functions are plugged. In this case only yocto-meteo but we could envision there are more.
  • Yocto-meteo: the device itself. In this screenshot, we could click on the it and get the temperature, humidity and pressure.
Anyway, we do not care about this UI. We are analyzing how to access it from a java source code, so let's use the JSON url which is: http://127.0.0.1:4444/api.json. The result you should get is something like this:


{
"module":{"productName":"VirtualHub","serialNumber":"VIRTHUB0-480741bdd3","logicalName":"","productId":0,"productRelease":1,"firmwareRelease":"6019","persistentSettings":0,"luminosity":50,"beacon":0,"upTime":4245111515,"usbCurrent":0,"realmHTTP":"YoctoDevices","adminPassword":"","userPassword":"","rebootCountdown":0,"usbBandwidth":0},
"services":{
"whitePages":[
{"serialNumber":"VIRTHUB0-480741bdd3","logicalName":"","productName":"VirtualHub","productId":0,"networkUrl":"/api","beacon":0,"index":0},
{"serialNumber":"METEOMK1-0268C","logicalName":"","productName":"Yocto-Meteo","productId":24,"networkUrl":"/bySerial/METEOMK1-0268C/api","beacon":0,"index":1}],
"yellowPages":{
"DataLogger":[
{"hardwareId":"METEOMK1-0268C.dataLogger","logicalName":"","advertisedValue":"OFF","index":0}],
"Temperature":[
{"hardwareId":"METEOMK1-0268C.temperature","logicalName":"","advertisedValue":"23.4","index":1}],
"Pressure":[
{"hardwareId":"METEOMK1-0268C.pressure","logicalName":"","advertisedValue":"958.0","index":2}],
"Humidity":[
{"hardwareId":"METEOMK1-0268C.humidity","logicalName":"","advertisedValue":"44.0","index":3}]}}}

There are a few interesting sections which are useful:


  • services.whitePages: contains the description of all the modules
  • service.yellowPages: contains the relevant values for the different modules
I decided to use the whitePages to get the information even if it is slightly more complex...

So, let's look on an whitePage entry:

{"serialNumber":"METEOMK1-0268C","logicalName":"","productName":"YoctoMeteo","productId":24,"networkUrl":"/bySerial/METEOMK1-0268C/api","beacon":0,"index":1}]

We can see already a lot of information:


  • The serial number which is unique to each yoctopuce device
  • The productId corresponding to the device. ProductName provides the same human-readable value
  • networkUrl: corresponds to the URL where to access the particular device values.
Let's take a deeper look on the network url and try to append the current URL + networkURL (http://127.0.0.1:4444/bySerial/METEOMK1-0268C/api): we get this page:


This provides us all the information about the selected device, in this case the yocto-meteo. As before, we do not care about the fancy widgets but only about the data: so let's append .json to the URL:



{
"module":{"productName":"Yocto-Meteo","serialNumber":"METEOMK1-0268C","logicalName":"","productId":24,"productRelease":1,"firmwareRelease":"5991","persistentSettings":2,"luminosity":50,"beacon":0,"upTime":231437,"usbCurrent":27,"realmHTTP":"YoctoDevices","adminPassword":"","userPassword":"","rebootCountdown":0,"usbBandwidth":0},
"humidity":{"logicalName":"","advertisedValue":"38.0","currentValue":2490368,"lowestValue":2490368,"highestValue":3145728},
"pressure":{"logicalName":"","advertisedValue":"959.0","currentValue":62783488,"lowestValue":62717952,"highestValue":62849024},
"temperature":{"logicalName":"","advertisedValue":"25.6","currentValue":1675264,"lowestValue":1458176,"highestValue":1675264},
"dataLogger":{"logicalName":"","advertisedValue":"OFF","oldestRunIndex":0,"currentRunIndex":1,"samplingInterval":1,"timeUTC":0,"recording":0,"autoStart":0,"clearHistory":0}}

And we get here, the temperature, pressure, humidity, etc. Now that we have everything, we can start the development and write a JAVA API.