User Tools

Site Tools


2017_2018:s3:concprogobjet:td:td7

Digital Home : application des DP

Objectifs de ce TD :

  1. Appréhender une petite application dans sa totalité
  2. Savoir utiliser un patron “State”
  3. Savoir utiliser un patron “Observer” et “Composite”

Les temps indiqués sont là pour vous aider. Il s'agit des temps maximum.

Cadre général

Un “maison numérique” est équipée de “dispositifs” dont les capteurs qui sont des composants qui permettent de relever des mesures.

Les “capteurs” sont soit associés à la maison (par exemple, un thermostat central), soit associés à une partie de la maison (par exemple, un capteur de consommation électrique à l'étage, un détecteur de fumée dans l'espace enfant), aux pièces (interrupteurs, thermomètre, …).

Un tableau de contrôle permet de visualiser les valeurs relevées par tous les capteurs de la maison.

Notre objectif est de permettre de :

  1. créer des maisons numériques auxquelles on peut ajouter des dispositifs,
  2. visualiser les valeurs des différents dispositifs contenus dans la maison.

Les capteurs physiques sont des dispositifs qui présentent une grande variabilité. Nous allons les gérer via des composants logiciels.

QUESTION (15 mn):

  • Analyser le problème sur papier (préparation à l'examen).
    • Vous devez maintenant savoir seuls ce dont vous avez besoin pour analyser un problème.
    • Vous devez vérifier que vous savez faire les diagrammes sans outil.
    • Représentez le scénario suivant sous la forme d'un diagramme de séquence en conception :
      1. L'utilisateur sélectionne sur l'écran du tableau de bord, “Mise à jour”
      2. Le tableau de bord recherche tous les capteurs de la maison et demande à chacun sa valeur courante,
      3. Les capteurs logiciels interrogent les capteurs physiques pour récupérer leur valeur,
      4. Le tableau de bord demande l'affichage à son écran de toutes les valeurs des capteurs pièce par pièce. Pour cela, il lui envoie une chaine de caractères qui correspond à l'affichage à produire.

Capteurs Physiques

Détecteur de mouvement
Capteur de température et humidité

Hélas nous ne disposons pas de “capteurs physiques”… Faisons comme si nous avions ces capteurs en les simulant par des capteurs physiques dont le code vous est donné. Il s'agit d'un “composant” très simple qui lit et écrit une valeur dans un fichier. Il vous sert de “bouchon” puisque nous ne disposons pas d'un vrai capteur physique auquel nous connecter.

QUESTION (5 mn):

  • Récupérer le code “bouchon” du capteur Physique. VOUS n'avez pas le droit de le modifier !! ; vérifiez que les tests passent bien avant de passer à la suite.
Attention de manière générale on ne fait pas des tests sur des “string” pour tester l'état des objets.

On ne lève pas des Throwable mais des exceptions dédiées qui expriment clairement l'exception détectée (http://www.wikijava.org/wiki/10_best_practices_with_Exceptions#Throw_only_Exceptions)

Capteurs logiciels

Les capteurs “logiciels” sont des capteurs qu'il faut interroger pour obtenir la valeur correspondant par exemple à une température ou un éclairage. A un capteur logiciel nous associons un capteur physique. A votre convenance un capteur logiciel peut modifier la valeur lue dans le capteur physique pour lui associer une unité e.g. getValue pour un capteur de température retournera la valeur plus “°C”, “18 °C”.

Attention, un capteur logiciel renvoie des valeurs sous la forme d'une String. S'il y a une erreur d'accès au capteur physique quelqu'elle soit, on doit avoir en réponse “bad value”.

QUESTION (15 mn):

  1. Mettez à jour votre diagramme de classe si besoin.
  2. Définir la classe Capteurlogiciel en lui associant un CapteurPhysique.
  3. Tester vos capteurs logiciels.

Capteurs logiciels à état

Certains capteurs peuvent changer d'état.

  • Dans l'état “Off”, lorsque on lui demande ses données, il répond “Off”.
  • Dans l'état “On”, lorsque on lui demande ses données, il demande au capteur physique qui lui est associé.
  • Dans l'état “Lazy”, lorsque on lui demande ses données, il ne demande la valeur au capteur physique que s'il ne l'a pas déjà ou que la valeur qu'il a sauvegardé date de plus de x temps. De cette manière on souhaite faire des économies d'énergie.

Un tel capteur change d'état sur ordre : “on”, “off”, “lazy”.

Pour obtenir le temps courant:

long startTime = System.currentTimeMillis();

Exemple de code pour tester l'état “Lazy” :

public class StateLazyTest {
 
	StateLazy sl;
	Sensor ps = ....;
 
	@Before
	public void setUp() throws Exception {
		ps.setValue("18");
		sl = new StateLazy(ps);
	}
 
	@Test
	public void test() throws NonAccessibleSensorException, MalFormatteeCapteurException, InterruptedException {
		String v = sl.getValue();
		assertEquals("18",v);
		ps.setValue("20");
		assertEquals("Lasy access : value non modified", "18", sl.getValue());
	    Thread.sleep(150);
		assertEquals("wake up : value modified", "20",  sl.getValue() );
		assertEquals("value modified", "20",  sl.getValue() );
	}

QUESTION (15 mn):

  1. Mettez à jour votre diagramme de classe si besoin en identifiant bien les éléments de design pattern.
  2. Définissez la classe CapteurOnOffLazy
  3. Testez votre classe, voici des exemples si cela peut vous aider.
	@Before
	public void setUp() throws Exception {
		  ps = new PhysicalSensor("mySensorLux");
	      sOnOffLazy = new SensorOnOff(ps);
	      sOnOffLazy.setValue("18");
	}
 
	@After
	public void tearDown() throws Exception {
	}
 
	@Test
	public void testStateInit() {
		assertEquals("Off at the beginning","off",sOnOffLazy.getValue());
	}
 
	@Test
	public void testStateOn() throws IOException, NonAccessibleSensorException {
		sOnOffLazy.on();
		assertEquals("On","18",sOnOffLazy.getValue());
		sOnOffLazy.setValue("20");
		assertEquals("On","20",sOnOffLazy.getValue());
	}
 
	@Test
	public void testStateOnOff() throws IOException, NonAccessibleSensorException {
		sOnOffLazy.on();
		assertEquals("On","18",sOnOffLazy.getValue());
		sOnOffLazy.off();
		assertEquals("off",sOnOffLazy.getValue());
	}
 
 
 
 
	@Test
	public void testStateLazy() throws IOException, NonAccessibleSensorException, InterruptedException {
		sOnOffLazy.lazy();
		assertEquals("18",sOnOffLazy.getValue());
		sOnOffLazy.setValue("20");
		assertEquals("Lasy access : value non modified", "18", sOnOffLazy.getValue());
	    Thread.sleep(150);
		assertEquals("wake up : value modified", "20",  sOnOffLazy.getValue() );
		assertEquals("value modified", "20",  sOnOffLazy.getValue() );
	}
 

QUESTION (10 mn): (Facultatif)

  • On veut définir des capteurs à un seul bouton (appel de la méthode press).
    • L'état de départ est off.
    • Dans l'état Off, si on appuie une fois (2 appels à off), on est On.
    • Dans l'état On si on appuie 2 fois (2 appels à on) on est Lazy.
    • Dans l'état Lazy si on appuie 2 fois (2 appels à lasy) on est Off.
  1. Mettez à jour votre diagramme de classe si besoin.
  2. Définir la classe CapteurOneButton

Pièce équipée

Une pièce est équipée de capteurs. On peut ajouter des capteurs à la pièce. On peut obtenir tous les capteurs de la pièce.

QUESTION (10 mn):

  1. Complétez ou corrigez si besoin votre diagramme de classe.
  2. Implémentez la classe Piece
  3. Créez un jeu de tests vous permettant de tester votre classe Piece.

Exemple de l'appel d'affichage suite à l'appel à toString sur une pièce:

Salon
	thermometre:19.0	humidite:12.7	lumiere:120.0

Maison numérique

Une maison numérique est une composition de parties dont certains parties sont elles-même des compositions de parties (l'étage est composé de la partie enfant et du bureau) et d'autres sont des pièces (bureaux, chambres, ..).

Il doit être possible d'interroger une partie de la maison pour connaitre tous les capteurs qu'elle contient : Pour une pièce, les capteurs qui lui sont associés, pour une partie composite, ses propres capteurs (par exemple, le thermostat de l'étage) + les capteurs des parties qui la compose.

Voici la maison que vous devez modéliser :

  1. Un RDC, un étage et un extérieur.
  2. Un étage avec 2 chambres, chacune avec son thermometre et un thermostat global à l'étage
  3. etc.

QUESTION (25 mn):

  • Modélisez la classe MaisonNumerique et tout ce qui est nécessaire pour répondre aux exigences.
  • Avez-vous utilisé un ou des DP? Si oui, annotez vos classes avec des “stéréotypes” permettant d'identifier les différents rôles joués par vos classes.
  • Implémentez et testez la.
  • Implémentez la maison donnée ci-après, et vérifiez que vous êtes bien capable de la représenter.
Oui oui, l'énoncé n'est pas mâché… Il est possible que vous deviez réécrire des codes, mais maintenant ce n'est plus un problème n'est-ce pas?

Posez bien votre nouveau modèle sur papier avant d'implémenter.

Voici une nouvelle maison, décrite un peu différemment.

maison = new Maison();
rdc = new PartieMaison("RDC");
cuisine = new Piece("Cusine");
sam = new Piece("Salle e manger");

parentalPart = new PartieMaison("Partie Parentale");
chambreParents = new Piece("parents");
sdbParent = new Piece("salle de bain des parents");
parentalPart.addLieu(chambreParents);
parentalPart.addLieu(sdbParent);
parentalPart.addSensor(thermostatParental);

rdc.addLieu(cuisine);
rdc.addLieu(sam);
rdc.addLieu(parentalPart);


etage = new PartieMaison("Etage");
chambre1 = new Piece("Chambre1");
chambre2 = new Piece("Chambre2");
etage.addLieu(chambre2);
etage.addLieu(chambre1);

exterieur = new PartieMaison("Exterieur");
exterieur.addSensor(externeDetecteurLumiere);
maison.addLieu(rdc);
maison.addLieu(etage);
maison.addLieu(exterieur);

Tableaux de Contrôle

Un tableau de contrôle permet de visualiser les capteurs associés aux lieux qu'il surveille. Pour cela, à chaque fois que l'on ajoute un capteur aux lieux surveillés, il ré-affiche la valeur de tous les capteurs. Attention, si je surveille le RDC, je surveille tous les capteurs du RDC pas seulement ceux qui sont en dehors des pièces!

Dans notre exemple, nous avons mis un tableau de contrôle au RDC et un à l'étage et un pour toute la maison. On ajoute un thermomètre dans la cuisine et on ajoute un de capteur de luminosité à l'étage, ainsi qu'un capteur de présence à l'extérieur. On vérifie que nos tableaux de bord se sont bien mis à jour.

TB MAISON

Thermostat RDC : 20
Thermometre SAM : 20
Thermostat Etage : 18
ThermometreChambre1 : 18.5
ThermometreChambre2 : 19.5
Luminosite : 100
Luminosité Etage : 80
Presence : true
Thermometre Cuisine : 19

TB RDC

Thermostat RDC : 20
Thermometre SAM : 20
Thermometre Cuisine : 19

TB ETAGE

Thermostat Etage : 18
ThermometreChambre1 : 18.5
ThermometreChambre2 : 19.5
Luminosité Etage : 80
Attention, ce n'est pas “facile”, mais c'est à votre niveau !

Optionnel

Pour s'amuser… évidemment dès que la valeur d'un des capteurs surveillé par un tableau de contrôle change de valeur, le tableau de bord se réaffiche…

Placer bien vos lignes de codes et vous n'avez presque rien à faire!!

Capteurs actifs (Facultatifs)

Un capteur actif est associé à un capteur physique. Il scrute régulièrement la valeur physique du capteur physique qui lui est associé et notifie ses observeurs chaque fois qu'il détecte un changement.

A présent les tableaux de bord sont mis à jour à chaque fois qu'un capteur actif d'un lieu sous surveillance est mis à jour.

Voici les éléments de code dont vous avez besoin pour définir un capteur actif:

  • Ce code vous permet de le déclarer comme pouvant s'exécuter “dans une thread à part” :
    public class CapteurActif  ... implements... Runnable{
  • Ce code est une méthode de votre CapteurActif qui explicite la boucle qui va lire le composant physique:
     public void run() {
    		System.out.println("Run lancé");
    		while (!stop) {
    			try {
    				Thread.sleep(2000);
    				if (!(valeurCourante.equals(getValeur())))  {
    					setValeurCourante(getValeur());
    				}
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	}
  • Le code suivant vous permet de “lancer” votre capteur :
CapteurActif cpTemporaire = new CapteurActif(new CapteurPhysique("cp1"));	
Thread threadCP= new Thread(cpTemporaire);
threadCP.start();

QUESTION (30mn) :

  • Définir les capteurs actifs et les connecter aux tableaux de bord.

Un peu de recul sur l'application

C'est juste des remarques.
  1. Si la maison est équipée de 10 capteurs et que chaque capteur est mis à jour toutes les secondes, …. votre tableau de bord se réaffiche 10 fois par seconde…
  2. Si maintenant vous réfléchissez au niveau de la ville… Les tableaux de bord ne sont pas directement “connectés” aux capteurs… d'autres approches par exemple avec des “files d'évènements” qui doivent vous rappeler le bus du 1e TD seront préférables…

Robots

Dans notre maison nous plaçons des petits robots.

Nous avons des robots “surveillant”. En mode repos, le robot surveillant attend que quelqu'un lui demande de passer en mode contrôle. En mode contrôle, il interroge toutes les pièces et envoie toutes les valeurs relevées sur un “bus dédié” en précisant l'heure et le lieu des relevés. Une fois qu'il a fait le tour de toutes les pièces de la maison, il passe en mode surveillance. En mode surveillance, il ne surveille que certains capteurs (par exemple, un détecteur de fumée et un détecteur de présence) et déclenche son alarme (capteur dédié) quand ils changent de valeur. Il passe alors en mode Alerte. Il ne peut sortir de cet état que si on le fait passer en mode repos ou si les capteurs qu'il surveille ont retrouvé leur valeur initiale (par exemple le détecteur de fumée est sur non et le détecteur de présence aussi), il retourne alors en mode Surveillance.

Pour ceux qui ont fini le reste et ont du temps..

Nous avons un drone qui est équipé de plusieurs capteurs. En mode contrôle, il se déplace dans les pièces et envoie toutes les valeurs relevées à un bus dédié en précisant l'heure et le lieu des relevés. Une fois qu'il a fait le tour de toutes les pièces de la maison, il passe en mode surveillance. Vous simulerez les relevés de mesure en fonction des lieux comme bon vous semble En mode surveillance, il contrôle régulièrement l'état de son capteur de détection de présence et s'il passe à “présence détecté”, il met la valeur de l'alarme (capteur propre au drône) à en marche et passe en mode Alerte. Il ne peut sortir de cet état que en lui donnant l'ordre de passer en mode contrôle.

Rendu

Rendu en fonction du groupe de TD : 15 décembre 2017

  • Dépôt sur Jalon pour Mme Blay-Fornarino avec une archive à vos Noms, qui contient :
  • Un document contenant
    • votre modèle de classe final intégré dans un document pour que nous n'ayons pas à ouvrir différents modèles dans différentes versions de l'outil,
    • des explications sur les raisons de ce modèle (dont vous êtes très fiers) et les leçons apprises.
  • Les codes et les tests.

http://java-design-patterns.com/blog/controlling-access-with-proxy-pattern/

https://github.com/iluwatar/java-design-patterns/tree/master/composite

2017_2018/s3/concprogobjet/td/td7.txt · Last modified: 2017/12/06 10:42 by blay