Capter des températures, avec une interface graphique
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Clément FRÉVILLE 07c1c83e5f
Use doubles to generate random temperatures
2 years ago
resources Switch to a toggle button 2 years ago
src/fr/uca/iut/clfreville2 Use doubles to generate random temperatures 2 years ago
.gitignore Initial commit 3 years ago
Ebullition.iml Initial commit 3 years ago
README.md Use doubles to generate random temperatures 2 years ago

README.md

Ebullition

Une application Java et JavaFX pour gérer des capteurs de température.

Usage

Sur la partie gauche de l'application figure l'arborescence des capteurs.

Un nouveau capteur peut être ajouté à la liste en saisissant son nom dans le champ de texte, son type et en appuyant sur le bouton Create. Il sera alors ajouté à la racine de l'arborescence et si le capteur qui était sélectionné est un capteur virtuel, il sera également ajouté comme source de ce dernier.

Une source de capteur virtuel peut être supprimée en sélectionnant le capteur virtuel puis en utilisant le menu contextuel sur la source à supprimer.

Les indicateurs liés à la génération automatique de température sont présentés en bas de l'application. Ils permettent d'activer ou non la génération automatique de température et de choisir la fréquence d'actualisation.

Conception

Note : les diagrammes UML présentés ci-dessous sont générés avec Mermaid, et peuvent ne pas être rendus correctement sur CodeFirst. Les flèches d'héritage n'ont notamment pas la bonne forme.

Interfaces partagées

classDiagram
    class Tickable {
        +tick()*
    }
    <<interface>> Tickable
    class Nameable {
        +getName()* String
        +getDisplayName() String
    }
    <<interface>> Nameable
    class Identifiable {
        +getId()* int
        +setName(name : String)*
    }
    <<interface>> Identifiable
    class ObservableIdentifiable {
        +idProperty()* ReadOnlyIntProperty
        +getId() int
        +nameProperty()* StringProperty
        +getName() String
        +setName(name : String)
        +displayNameExpression() StringExpression
        +getDisplayName() String
    }
    <<interface>> ObservableIdentifiable
    class SensorFactory {
        +create(registry : SensorRegistry, name : String)* Sensor
    }
    <<interface>> SensorFactory
    class AutoUpdateStrategyFactory {
        +create()* AutoUpdateStrategy
    }
    <<interface>> AutoUpdateStrategyFactory
    Nameable <|-- Identifiable
    Identifiable <|-- ObservableIdentifiable
    Nameable <|-- SensorFactory
    Nameable <|-- AutoUpdateStrategyFactory

L'interface Tickable définit une méthode tick qui est appelée périodiquement par un thread.

Tous les objets héritent en Java de java.lang.Object et ont donc une méthode toString utilisée principalement pour déboguer. Lorsqu'un objet est fait pour être affiché à l'utilisateur, ce n'est pas du débogage. L'interface Nameable définit les méthodes getName et getDisplayName qui retourne les noms à afficher pour ces objets.

Un objet peut être identifié par un identifiant unique, un UUID ou un int. L'interface Identifiable définit la méthode getId qui permet de récupérer cet identifiant sous forme d'entier. Elle définit aussi une méthode setName pour changer le nom de l'objet.

Des objets qui implémentent Nameable ou Identifiable ne sont pas nécessairement observables. C'est pourquoi l'interface ObservableIdentifiable hérite de ces deux interfaces et expose les propriétés observables pour l'identifiant et le nom. Il s'agit du même nom que les méthodes getId et getName mais en exposant une propriété observable.

D'autres éléments de l'application sont nommables, comme certaines fabriques d'objets : SensorFactory crée des capteurs et AutoUpdateStrategyFactory crée des stratégies d'actualisation automatique. Ces deux interfaces héritent de Nameable pour proposer un affichage de ces fabriques dans l'application.

Capteurs

classDiagram
    class ObservableIdentifiable {
        ...
    }
    <<interface>> ObservableIdentifiable
    class Tickable {
        +tick()*
    }
    <<interface>> Tickable
    class Sensor {
        -id : IntegerProperty
        -name : StringProperty
        -displayName : StringExpression
        -temperature : DoubleProperty
        +Sensor(id : int, name : String)
        +idProperty() int
        +nameProperty() StringProperty
        +displayNameExpression() StringExpression
        +temperatureProperty() ReadOnlyDoubleProperty
        +getTemperature() double
    }
    class ManualSensor {
        +temperatureProperty() DoubleProperty
    }
    class AutoSensor {
        -updateStrategy : ObjectProperty~AutoUpdateStrategy~
        +tick()
        +getUpdateStrategy() AutoUpdateStrategy
        +setUpdateStrategy(s : AutoUpdateStrategy)
        +updateStrategyProperty() ReadOnlyObjectProperty~AutoUpdateStrategy~
    }
    class VirtualSensor {
        -sources : ObservableList~DataSource~
        -sourcesProperty : ListProperty~DataSource~
        +addSource(s : Sensor, weight : double)
        +removeSource(s : Sensor) bool
        +sourcesProperty() ReadOnlyListProperty~DataSource~
        #compute()
    }
    class DataSource {
        -sensor : Sensor
        -weight : DoubleProperty
        +sensor() Sensor
        +weight() double
    }
    Sensor <|-- ManualSensor
    Sensor <|-- AutoSensor
    Sensor <|-- VirtualSensor
    ObservableIdentifiable <|.. Sensor
    Tickable <|.. AutoSensor
    DataSource "*" <-- VirtualSensor
    Sensor "1" <-- DataSource

Un capteur est un objet observable et identifiable.

S'il peut être mis à jour périodiquement comme c'est le cas pour les capteurs automatiques AutoSensor, il implémente l'interface Tickable.

Un capteur manuel ne fait qu'autoriser publiquement la modification de la température par rapport à la classe abstraite Sensor.

Un capteur virtuel est composé de plusieurs sources de température. C'est une variante du patron de conception composite : chaque capteur virtuel contient une liste de capteurs et de poids associés avec des objets DataSource.

Stratégies d'actualisation automatique

classDiagram
    class AutoUpdateStrategy {
        +nextValue(s : AutoSensor)* double
        +getType()* AutoUpdateStrategyFactory
    }
    <<interface>> AutoUpdateStrategy
    class RandomUpdateStrategy {
        -random : Random
        -min : double
        -max : double
        +nextValue(s : AutoSensor) double
        +getType() AutoUpdateStrategyFactory
    }
    class RandomVariationStrategy {
        -random : Random
        -maxVariation : double
        +nextValue(s : AutoSensor) double
        +getType() AutoUpdateStrategyFactory
    }
    class CpuUpdateStrategy {
        +nextValue(s : AutoSensor) double
        +getType() AutoUpdateStrategyFactory
    }
    AutoUpdateStrategy <|.. CpuUpdateStrategy
    AutoUpdateStrategy <|.. RandomUpdateStrategy
    AutoUpdateStrategy <|.. RandomVariationStrategy