|
|
Rappels :
Vous devez fournir des copies d'écran des diagrammes de classe de BlueJ,
et la documentation générée doit faire apparaître
vos commentaires sur toutes les classes, les méthodes, les paramètres,
et les valeurs de retour.
Question 1. (Acquisition cyclique)
(i) Il s'agit de se connecter à un capteur qui est
connecté à internet (il a sa propre URL !).
le source de cette page :
# ibutton: DS2438; Adapter: DS9097U; Port:
COM2;<br>1C0000000D536B26=36.58370195823707
(1C0000000D536B26 représente le numéro du composant,
36.58370195823707 le taux d'humidité relative)
ii) Lire le source de la classe HTTPHumidity,
effectuer plusieurs tests.
Ajouter une nouvelle méthode à cette classe permettant de lire la
valeur de l'humidité relative fournie par ce capteur. Pour répondre à cette
question, vous devez utiliser la classe java.util.StringTokenizer
.
Cette méthode a la signature suivante :
public float value() throws Exception;
la valeur retournée aura un seul chiffre après la virgule, (précision 0.1 du composant)
iii) Complétez la classe
CyclicAcquisition, contenant un Thread local. Ce
Thread permet l'acquisition cyclique du taux d'humidité, la période doit être
supérieure à 1 minute (contrainte à respecter afin de pas surcharger
le serveur Web au Cnam).
Cette version néglige le temps de communication :
Requête HTTP et analyse du résultat. L'information reçue est affichée sur la
console par une implémentation de l'interface Command, plus particulièrement la méthode
make.
L'interface Command :
public interface Command{
public void make(float f);
}
(iv) Fournir une classe de test pour la classe AcquisitionSystem ci-dessous; un des tests sera de s'assurer que le proxy de l'esiee est bien en place avant d'effectuer la moindre requête HTTP, des tests sur la valeur de ce taux d'humidité pourront être installés (100% à l'intérieur d'un bureau ne devrait pas se produire), ...
package acquisition; public class AcquisitionSystem implements Command{ private String url; private long period; private Handler chain; private CyclicAcquisition cyclic; public AcquisitionSystem(String url,long period,Handler chain){ this.url = url; this.period = period; this.chain = chain; cyclic = new CyclicAcquisition(url,period,this); cyclic.start(); } public AcquisitionSystem(Handler chain){ this("http://lmi92.cnam.fr:8999/ds2438/",CyclicAcquisition.ONE_MINUTE,chain); } public void stop(){ cyclic.stop(); } public void make(float f){ chain.handleRequest(f); } }
AIDE :
|
(v) Fournissez la documentation regroupant toutes les classes des questions précédentes.
Question 2. (Chaîne de responsabilités)
(i) L'information reçue, le taux d'humidité, est maintenant
transmise à différents consommateurs. Les consommateurs sont chainés entre eux.
Ce type de conception est issu du pattern "chaîne de responsabilités". Le principe est de transmettre l'information à une chaîne de
consommateurs, chaque consommateur décide si il doit laisser passer
l'information vers son successeur ou bien arrêter sa propagation.
La classe abstraite Handler adaptée, selon la bibliographie :
public abstract class Handler{ protected Handler successor = null; public Handler(){ this.successor = null;} public Handler(Handler successor){ this.successor = successor;} public void setSuccessor(Handler successor){this.successor = successor;} public Handler getSuccessor(){return this.successor;}
public boolean handleRequest(float value){ if ( successor == null ) return false; return successor.handleRequest(value); } }
(ii) Proposer une première "Chaîne de responsabilités" constituée de 3 "Handlers" liée à notre application de lecture cyclique du taux d'humidité
Les "Handlers" seront chainés comme suit TraceHandler -> MinHandler -> MaxHandler
La classe TraceHandler ci-dessous :
public class TraceHandler extends Handler{ public TraceHandler(Handler successor){ super(successor); } public boolean handleRequest(float value){ /* affichage de la valeur */ return super.handleRequest(value); } }
Une Trace d'exécution possible :
value : 36.6 value : 36.9 value : 36.6 value : 36.2 value : 36.6 value : 36.2 |
value : 30.6 value min détectee : 30.6 value : 30.6 value min détectee : 30.6 value : 30.7 value min détectee : 30.7 value : 30.7 value min détectee : 30.7 value : 30.7 value min détectee : 30.7 value : 31.1 value min détectee : 31.1 |
value : 37.7 value : 37.7 value : 37.7 value : 37.7 value : 37.7 value : 37.8 |
(iii) Ajouter deux nouveaux maillons au bon endroit dans la chaîne :
AIDE :
|
(iv) Ajouter encore un maillon dans la chaîne : FileHandler, ce 'handler' est chargée de la sauvegarde sur fichier des mesures
Les "Handlers" seront chainés comme suit TraceHandler -> FileHandler -> Le reste de la chaîne
<html><head><title>mesures</title></head><body><table border="2" bgcolor="#CBFEEA">
<tr>
<td>15/10/03-16:46</td>
<td>26.6</td>
</tr>
<tr>
<td>15/10/03-16:56</td>
<td>27.1</td>
</tr>
<tr>
<td>15/10/03-17:06</td>
<td>26.5</td>
</tr>
<tr>
<td>15/10/03-17:16</td>
<td>26.7</td>
</tr>
<tr>
<td>15/10/03-17:26</td>
<td>28.2</td>
</tr>
</table></body></html>
15/10/03-16:46 26.6 15/10/03-16:56 27.1 15/10/03-17:06 26.5 15/10/03-17:16 26.7 15/10/03-17:26 28.2
(v) Fournissez la documentation regroupant toutes les classes des questions précédentes.
OPTIONNEL* :Question 3. (température)
(i) Complétez toutes les classes précédentes pour qu'elles gèrent
la température de la pièce en plus du taux d'humidité.
(ii) Fournissez la documentation regroupant toutes les classes.
|
Humidité Relative : définition extraite de
http://www.credo.fr/monde/page/pf_090799.htm
L'Humidité Relative (HR) exprime le rapport entre la quantité
effective de vapeur d'eau dans un volume donné d'air et la quantité maximale que
ce volume peut contenir à la même température.
L'eau s'évapore dans
l'atmosphère jusqu'à ce que soit atteinte une proportion maximale de vapeur
d'eau dans l'air, dite humidité saturante.
Quand cette condition est
atteinte, la moindre chute de température provoque la condensation de la vapeur
et l'apparition de minuscules gouttes d'eau. Il s'agit du phénomène de
rosée.
La saturation de l'air en vapeur d'eau (ou point de rosée) correspond
donc à 100 % d'humidité relative.
La
quantité de vapeur d'eau dans l'air à 100 % HR est d'environ 15 grammes d'eau
par mètre cube d'air.
Quand la quantité de vapeur d'eau dans l'air est en
deçà de la saturation, l'humidité relative est infèrieure à 100 %.
A peu de
choses près, une HR de 70 % correspond à une quantité d'eau par mètre cube d'air
de 70 % de la quantité présente à saturation: environ 10,5 grammes d'eau par
mètre cube d'air.
Annexe 1.Source de HTTPHumidity.java
// tp7-1ii : HTTPHumidity.java package sensor; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; import java.util.Hashtable; import java.util.Enumeration; import java.util.Properties; import java.util.StringTokenizer; /** Classe de lecture d'un capteur sur le Web * @version de test * @author jm Douin */ public class HTTPHumidity{ /** l'URL associée au capteur */ private String urlSensor; /** Constructeur d'une connexion avec un Capteur * @param urlSensor l'URL du capteur sur le Web en protocole HTTP */ public HTTPHumidity(String urlSensor){ this.urlSensor = urlSensor; } /** Lecture de la valeur de humidité relative **/ public float Value() throws Exception{ /* Acquisition de la valeur */ } /** lecture de l'URL * @return l'url associée à ce capteur */ public String getUrl(){ return this.urlSensor; } /** Lecture des informations issues de ce capteur * @param params les paramètres * @return la totalité de la page lue * @throws Exception en cas d'erreur */ public String read(Properties params) throws Exception{ URL url = new URL(urlSensor); URLConnection connection = url.openConnection(); connection.setDoInput( true ); connection.setDoOutput(true); PrintWriter out = new PrintWriter(connection.getOutputStream()); // les paramhtres (type CGI) for(Enumeration e = params.keys();e.hasMoreElements();){ String key = (String) e.nextElement(); String value = (String) params.get(key); out.print(key + "=" + value); //System.out.println(key + "=" + value); if(e.hasMoreElements()) out.print("&"); } //out.println(); out.close(); // lecture en retour BufferedReader in = new BufferedReader( new InputStreamReader(connection.getInputStream())); String result= new String(""); String inputLine = in.readLine(); while(inputLine != null){ result = result + inputLine; inputLine = in.readLine(); } in.close(); return result; } /** Lecture des informations issues de ce capteur * @return la totalité de la page lue * @throws Exception en cas d'erreur */ public String read() throws Exception{ final Properties nil = new Properties(); return read(nil); } /** Mise en place du proxy si nécessaire * rappel à l'esiee : proxyHost=cache.esiee.fr proxyPort=3128 * attention, aucune vérification de la validité de l'URL transmise n'est effectuée * @param proxyHost adresse du proxy * @param proxyPort le port du proxy */ public static void setHttpProxy(String proxyHost,int proxyPort){ Properties prop = System.getProperties(); prop.put("proxySet","true"); prop.put("http.proxyHost",proxyHost); prop.put("http.proxyPort",Integer.toString(proxyPort)); } // bloc d'initialisation statique pour l'esiee private static final boolean ESIEE_INSIDE = true; static { if(ESIEE_INSIDE){setHttpProxy("cache.esiee.fr",3128);} } }
Annexe 2.Source de CyclicAcquisition.java
// tp7-1iii : CyclicAcquisition.java package acquisition; import sensor.HTTPHumidity; import java.util.Calendar; import java.text.DateFormat; public class CyclicAcquisition implements Runnable{ public static final long ONE_MINUTE = 60L * 1000L; private Thread local; private Command command; private HTTPHumidity sensor; private long period; public CyclicAcquisition(String url, long period, Command command){ assert period >= ONE_MINUTE : " respectez la période minimale (period*ms > minute) !!"; this.sensor = new HTTPHumidity(url); this.period = period; this.command = command; local = new Thread(this); } public void start(){ /* démarrer le thread */ } public void stop(){ /* interrompre le thread */ } public synchronized void setPeriod(long period){ this.period = period; } public void run(){ try{ while(!local.isInterrupted()){ synchronized( this ){ try{ /* lecture du capteur et utilisation de la valeur */ }catch( Exception e){ /* retour d'une valeur négative */ } Thread.sleep( period); } // synchronized } // while }catch( InterruptedException ie ){ System.out.println( "InterruptedException : " + ie.getMessage() + " at " + DateFormat.getTimeInstance().format(Calendar.getInstance().getTime()) ); } // catch } // run() }
Annexe 3.Source de FileHandler.java
// tp7-2iv : FileHandler.java package acquisition; import java.io.File; // import des classes de gestion des fichiers en ecriture import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.PrintWriter; import java.io.ObjectOutputStream; // import des classes de gestion des fichiers en lecture import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileReader; import java.io.ObjectInputStream; // exceptions susceptibles d'etre engendrees lors d'une operation de lecture ou d'ecriture import java.io.IOException; import java.io.FileNotFoundException; // exception liee a la serialisation import java.lang.ClassCastException; import java.util.Collection; /* à compléter */ import java.util.Calendar; import java.util.Locale; import java.util.Iterator; import java.util.Date; import java.text.DateFormat; // emploi de getResource (voir java.lang.Class) import java.net.URL; public class FileHandler extends Handler { private final static int MAX=5; private String fileName; private int counter; /* déclarer une table */ private SortedMap table; public FileHandler(String fileName, Handler successor) { /* à compléter */ } public boolean handleRequest(float value) { /* à compléter */ } /** Cette methode genere un fichier HTML . */ private void writeHTML() throws IOException{ BufferedWriter bw = new BufferedWriter( new PrintWriter( new FileOutputStream( new File(fileName + ".html")))); /* à compléter */ bw.close(); } /** Pour la serialisation : * Ecriture de la version binaire sur fichier d'une table des mesures. * @throws IOException Si le processus de sauvegarde echoue. */ private void write() throws IOException{ ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(fileName + ".ser")); os.writeObject(table); os.flush(); os.close(); } }