Travaux Pratiques

Thread, AsyncTask

Thème: Acquisition périodique d'un capteur installé sur le web

  • Ce capteur est un DS2438 qui délivre le taux d'Humidité Relative d'un bureau au CNAM/Paris 75003.
  • Il est relié au serveur lmi92.cnam.fr par un adaptateur port série <--> bus 1-Wire de Dallas Semiconductor/MAXIM.
  • Ce capteur est accessible à l'URL : http://lmi92.cnam.fr/ds2438/ds2438/
    • Une valeur aléatoire est retournée lorsque ce capteur est déconnecté du serveur lmi92, ce qui est fréquent...
    • Une API est fournie afin d'effectuer la requête et l'obtention de la valeur de ce capteur sous la forme d'un nombre flottant

    Si ce lien http://lmi92.cnam.fr/ds2438/ds2438/ ne répond pas, le serveur est en défaut, cf. en bas de la page de cet énoncé pour une solution en "local".

     

  • Question 1)

    Question1.1) Proposez une activité permettant d'effectuer une acquisition de la valeur de ce capteur toutes les N secondes (N>=1). Cette valeur, précédée de la date de lecture, est affichée sur l'écran du mobile. L'acquisition démarre à l'aide du bouton start et se termine en appuyant sur stop. Une jauge de type ProgressBar reflète la valeur lue.

    Ci-dessous quelques copies d'écran de l'activité souhaitée

    Note: Au démarrage, seul le bouton start est valide
    Dès l'acquisition, le bouton stop devient valide
    Le projet eclipse:

    HumiditySensorAbstract.java , la classe abstraite des capteurs d'humidité est fournie
    public abstract class HumiditySensorAbstract{
      /** valeur du capteur, précision de 0.1 */
    public abstract float value() throws Exception;
    /* période minimale entre deux lectures */
    public abstract long minimalPeriod();
    }
     


    HTTPHumiditySensor.java  une implémentation est prête à l'emploi pour un capteur de type HTTP
    la documentation de type javadoc.
     
    La création d'une instance et lecture d'une valeur s'effectuent par:

       HumiditySensorAbstract ds2438 = new HTTPHumiditySensor("http://lmi92.cnam.fr/ds2438/ds2438/");
       float taux = ds2438.value(); 
     

    Notes sur l'implémentation demandée: 

    <uses-permission android:name="android.permission.INTERNET"></uses-permission>

     

    Question 1.2) Ajoutez la possibilité de changer l'adresse du serveur associé au capteur, cette nouvelle adresse sera persistante.

    Une suggestion de modification de l'IHM utilisée en question 1, serait d'utiliser la zone d'affichage des valeurs acquises, afin de saisir une nouvelle URL, cette zone deviendrait éditable au clic sur l'écran, ce qui déclencherait l'arrêt de l'acquisition et l'apparition d'un bouton de prise en compte de la nouvelle URL (Set). L'utilisateur entrerait alors la nouvelle URL validée au clic sur le bouton de prise en compte. Ensuite, il suffirait de cliquer sur le bouton start pour démarrer un nouveau cycle d'acquisition avec ces nouvelles données. Cette URL pourrait être également persistante cf. les deux méthodes dans l'encadré ci-dessous.

    Ci-dessous, l'IHM suggérée en quelques copies d'écran, au clic sur l'écran le bouton Set apparaît, la zone de texte devient éditable, ce qui autorise l'entrée d'une nouvelle URL par l'utilisateur.

    Le bouton set devient visible en exécutant cette méthode: set.setVisibility(View.VISIBLE);

    Le clic sur l'écran pourrait utiliser l'attribut onClick de la déclaration XML associée à celui-ci

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:onClick="onClickView"
    android:orientation="vertical" >

    Avec au sein de votre activité, la méthode onClickView:

    public void onClickView(View v){
     
    if(acquisition!=null)onClickStop(v);
     
    set.setVisibility(View.VISIBLE);
     
    tv.setEnabled(true);
     
    tv.setText(serverAddress);
     
    tv.setFocusable(true);
     
    tv.setFocusableInTouchMode(true);
     
    start.setEnabled(false);
     
    stop.setEnabled(false);
    }


    Le bouton devient invisible: set.setVisibility(View.INVISIBLE);
     Deux méthodes utilitaires pour la persistance de l'URL du capteur:
     private static void saveURL_SENSOR(Context context, String url) {  
       SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);  
       Editor edit = prefs.edit();  
       edit.putString("url_sensor", url);  
       edit.commit();  
     }  
    			  
     private static String loadURL_SENSOR(Context context){
       SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
       return prefs.getString("url_sensor",URL_SENSOR);
     }
    Méthode utilitaire, extraite du web, pour la connectivité du mobile:
     public  final boolean isInternetOn() {
        final ConnectivityManager conMgr =  (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        final NetworkInfo activeNetwork = conMgr.getActiveNetworkInfo();
        if (activeNetwork != null && activeNetwork.isConnected()) {
    	return true;
        }
        return false;
      }
    		

     

    Question 2)  Le serveur dédié au capteur sur le web est maintenant installé sur un autre émulateur, celui-ci délivre exactement les mêmes informations, soit des valeurs aléatoires du capteur d'humidité.

    1. Installez ce serveur, soit cette application Android sur un émulateur, le projet eclipse au complet est ici.
    2. Il vous faut vous identifier
      auth auth_token  cf. .emulator_console_auth_token file in your home directory.
    3. Exécutez cette commande sur l'émulateur via telnet localhost 5554
    4. Depuis votre navigateur cette URL doit fonctionner http://localhost:8999/ds2438/
      • Vérifiez que c'est bien le serveur installé sur l'émulateur/serveur qui satisfait cette requête
    5. Exécutez un navigateur depuis un autre émulateur, (5556)
      • Menu Window item Android Virtual Device Manager puis sélectionnez un nouvel émulateur et start
    6. Exécutez votre application de la question 1.2 et entrez cette nouvelle URL,
    7. Installez de nouveau votre application sur un deuxième émulateur, puis un troisième soit trois clients, un serveur
    8. Vérifiez le bon fonctionnement ... émulateurs comme mobiles.
      • Optionnel, Avec au moins deux mobiles au sein du même réseau wifi, un serveur et un ou plusieurs clients
    9. Optionnel, vérifiez avec l'émulateur de Genymotion http://www.genymotion.com/ en serveur et comme client
      
    Le capteur/serveur installé sur un premier émulateur (5554)

    La zone de texte indique ce qui est retourné au client,
    soit l'URL du client, l'heure de la requête, le type de capteur et la valeur du capteur (ici 81.03331)
    Un client est installé sur un deuxième émulateur (5556), l'URL 10.0.2.2 correspond à localhost
     
    Un autre client depuis un navigateur de votre ordinateur (le serveur est l'émulateur installé en 5554)

    Le navigateur du deuxième émulateur(5556)

     

    Autre architecture possible: Le serveur et le client sont installés sur deux mobiles, même réseau wifi

    Notez que si votre mobile possède ce type de capteur c'est une valeur réelle qui est retournée...

    final SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    if(sensorManager!=null){
        List<Sensor> sensors = sensorManager.getSensorList(Sensor.
    TYPE_RELATIVE_HUMIDITY);
     

    Avec Genymotion,

    Le serveur est installé sur un émulateur

    Un client: votre navigateur: http://192.168.56.102:8999/ds2438/

    Un autre client: un autre émulateur Genymotion, sur le même poste

     

    Au cas où, en cas de panne côté serveur ( http://lmi92.cnam.fr/ds2438/ds2438/ )

           2)  depuis votre navigateur cliquez sur ce lien

    Le source de la page retournée

    # ibutton: DS2438; Adapter: DS9097U; Port: COM2;<br>1C0000000D536B26=21.923176
    (1C0000000D536B26 représente le numéro du composant, 21.923176 le taux d'humidité relative)

    côté serveur la fenêtre devrait mentionner