diff --git a/resources/windows/MainWindows.fxml b/resources/windows/MainWindows.fxml index 29427f6..0fe84c9 100644 --- a/resources/windows/MainWindows.fxml +++ b/resources/windows/MainWindows.fxml @@ -14,7 +14,7 @@ - +
@@ -28,6 +28,9 @@ +
+ +
diff --git a/src/fr/uca/iut/clfreville2/gui/MainWindows.java b/src/fr/uca/iut/clfreville2/gui/MainWindows.java index 635ca4a..c9b1216 100644 --- a/src/fr/uca/iut/clfreville2/gui/MainWindows.java +++ b/src/fr/uca/iut/clfreville2/gui/MainWindows.java @@ -11,15 +11,21 @@ import fr.uca.iut.clfreville2.gui.tree.SensorTreeCell; import fr.uca.iut.clfreville2.gui.tree.SensorTreeItemBridge; import fr.uca.iut.clfreville2.model.SensorRegistry; import fr.uca.iut.clfreville2.model.binding.ToBooleanBinding; +import fr.uca.iut.clfreville2.model.sensor.AutoSensor; import fr.uca.iut.clfreville2.model.sensor.ManualSensor; import fr.uca.iut.clfreville2.model.sensor.Sensor; import fr.uca.iut.clfreville2.model.sensor.VirtualSensor; +import fr.uca.iut.clfreville2.model.sensor.auto.AutoUpdateStrategy; +import fr.uca.iut.clfreville2.model.sensor.auto.provider.AutoUpdateStrategyProvider; +import fr.uca.iut.clfreville2.model.sensor.auto.provider.StandardUpdateStrategyProvider; import fr.uca.iut.clfreville2.model.sensor.provider.AutoSensorProvider; import fr.uca.iut.clfreville2.model.sensor.provider.ManualSensorProvider; import fr.uca.iut.clfreville2.model.sensor.provider.SensorProvider; import fr.uca.iut.clfreville2.model.sensor.provider.VirtualSensorProvider; import fr.uca.iut.clfreville2.persistence.StubSensorRegistryLoader; import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.fxml.FXML; import javafx.scene.control.Button; @@ -57,6 +63,10 @@ public class MainWindows { @FXML private Button changeBtn; + @FXML + private ChoiceBox autoType; + private final ChangeListener autoUpdateChangeHandler = this::changedUpdateStrategy; + @FXML private Button visualizeBtn; @@ -150,10 +160,17 @@ public class MainWindows { sensorName.textProperty().unbindBidirectional(oldValue.getValue().nameProperty()); sourcesView.itemsProperty().unbind(); sourcesView.setItems(FXCollections.emptyObservableList()); + if (oldValue.getValue() instanceof AutoSensor auto) { + auto.updateStrategyProperty().removeListener(autoUpdateChangeHandler); + } } if (newValue != null && newValue.getValue() != null) { sensorId.textProperty().bind(newValue.getValue().displayNameExpression()); sensorName.textProperty().bindBidirectional(newValue.getValue().nameProperty()); + if (newValue.getValue() instanceof AutoSensor auto) { + auto.updateStrategyProperty().addListener(autoUpdateChangeHandler); + changedUpdateStrategy(null, null, auto.getUpdateStrategy()); + } if (newValue.getValue() instanceof VirtualSensor virtual) { sourcesView.itemsProperty().bind(virtual.sourcesProperty()); } @@ -171,6 +188,10 @@ public class MainWindows { treeItem -> treeItem != null && treeItem.getValue() instanceof ManualSensor )); visualizeBtn.visibleProperty().bind(sensorTree.getSelectionModel().selectedItemProperty().isNotNull()); + autoType.visibleProperty().bind(new ToBooleanBinding<>( + sensorTree.getSelectionModel().selectedItemProperty(), + treeItem -> treeItem != null && treeItem.getValue() instanceof AutoSensor + )); } @FXML @@ -195,6 +216,16 @@ public class MainWindows { @FXML private void bindProvidable() { + autoType.getItems().addAll(StandardUpdateStrategyProvider.values()); + autoType.setConverter(new NameableStringConverter<>(autoType.getItems())); + autoType.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + Sensor selected = getSelectedSensor(); + if (!(selected instanceof AutoSensor sensor)) { + return; + } + sensor.setUpdateStrategy(newValue.create()); + }); + createType.getItems().addAll( new ManualSensorProvider(), new AutoSensorProvider(), @@ -224,4 +255,8 @@ public class MainWindows { } virtual.removeSource(source); } + + private void changedUpdateStrategy(ObservableValue ___, AutoUpdateStrategy o, AutoUpdateStrategy n) { + autoType.getSelectionModel().select(n.getType()); + } } diff --git a/src/fr/uca/iut/clfreville2/gui/thread/Ticker.java b/src/fr/uca/iut/clfreville2/gui/thread/Ticker.java index 40a725f..ed527f9 100644 --- a/src/fr/uca/iut/clfreville2/gui/thread/Ticker.java +++ b/src/fr/uca/iut/clfreville2/gui/thread/Ticker.java @@ -10,7 +10,7 @@ import javafx.beans.property.SimpleIntegerProperty; public class Ticker extends Thread { private final Tickable tickable; - private final IntegerProperty millisPerTick = new SimpleIntegerProperty(250); + private final IntegerProperty millisPerTick = new SimpleIntegerProperty(500); private final BooleanProperty running = new SimpleBooleanProperty(true); public Ticker(Tickable tickable) { diff --git a/src/fr/uca/iut/clfreville2/model/sensor/AutoSensor.java b/src/fr/uca/iut/clfreville2/model/sensor/AutoSensor.java index cbae785..e64e3a3 100644 --- a/src/fr/uca/iut/clfreville2/model/sensor/AutoSensor.java +++ b/src/fr/uca/iut/clfreville2/model/sensor/AutoSensor.java @@ -2,9 +2,13 @@ package fr.uca.iut.clfreville2.model.sensor; import fr.uca.iut.clfreville2.model.sensor.auto.AutoUpdateStrategy; import fr.uca.iut.clfreville2.model.shared.Tickable; +import javafx.beans.Observable; import javafx.beans.property.DoubleProperty; +import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyDoubleProperty; +import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.SimpleDoubleProperty; +import javafx.beans.property.SimpleObjectProperty; import static java.util.Objects.requireNonNull; @@ -14,16 +18,16 @@ import static java.util.Objects.requireNonNull; public class AutoSensor extends Sensor implements Tickable { private final DoubleProperty temperature = new SimpleDoubleProperty(); - private AutoUpdateStrategy updateStrategy; + private final ObjectProperty updateStrategy = new SimpleObjectProperty<>(); public AutoSensor(int id, String name, AutoUpdateStrategy updateStrategy) { super(id, name); - this.updateStrategy = requireNonNull(updateStrategy, "update strategy"); + this.updateStrategy.set(requireNonNull(updateStrategy, "update strategy")); } @Override public void tick() { - temperature.set(updateStrategy.nextValue(this)); + temperature.set(updateStrategy.get().nextValue(this)); } @Override @@ -32,10 +36,14 @@ public class AutoSensor extends Sensor implements Tickable { } public AutoUpdateStrategy getUpdateStrategy() { - return updateStrategy; + return updateStrategy.get(); } public void setUpdateStrategy(AutoUpdateStrategy updateStrategy) { - this.updateStrategy = requireNonNull(updateStrategy, "update strategy"); + this.updateStrategy.set(requireNonNull(updateStrategy, "update strategy")); + } + + public ReadOnlyObjectProperty updateStrategyProperty() { + return updateStrategy; } } diff --git a/src/fr/uca/iut/clfreville2/model/sensor/auto/AutoUpdateStrategy.java b/src/fr/uca/iut/clfreville2/model/sensor/auto/AutoUpdateStrategy.java index 4699952..bf39d66 100644 --- a/src/fr/uca/iut/clfreville2/model/sensor/auto/AutoUpdateStrategy.java +++ b/src/fr/uca/iut/clfreville2/model/sensor/auto/AutoUpdateStrategy.java @@ -1,8 +1,8 @@ package fr.uca.iut.clfreville2.model.sensor.auto; import fr.uca.iut.clfreville2.model.sensor.AutoSensor; +import fr.uca.iut.clfreville2.model.sensor.auto.provider.AutoUpdateStrategyProvider; -@FunctionalInterface public interface AutoUpdateStrategy { /** @@ -12,4 +12,11 @@ public interface AutoUpdateStrategy { * @return The next value of the sensor. */ double nextValue(AutoSensor currentState); + + /** + * Gets the type of this strategy. + * + * @return The type of this strategy. + */ + AutoUpdateStrategyProvider getType(); } diff --git a/src/fr/uca/iut/clfreville2/model/sensor/auto/CpuUpdateStrategy.java b/src/fr/uca/iut/clfreville2/model/sensor/auto/CpuUpdateStrategy.java new file mode 100644 index 0000000..6cdf275 --- /dev/null +++ b/src/fr/uca/iut/clfreville2/model/sensor/auto/CpuUpdateStrategy.java @@ -0,0 +1,27 @@ +package fr.uca.iut.clfreville2.model.sensor.auto; + +import fr.uca.iut.clfreville2.model.sensor.AutoSensor; +import fr.uca.iut.clfreville2.model.sensor.auto.provider.AutoUpdateStrategyProvider; +import fr.uca.iut.clfreville2.model.sensor.auto.provider.StandardUpdateStrategyProvider; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class CpuUpdateStrategy implements AutoUpdateStrategy { + + @Override + public double nextValue(AutoSensor currentState) { + try { + //return Integer.parseInt(Files.readString(Path.of("/sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon1/temp1_input")).trim()) / 1000D; + return Integer.parseInt(Files.readString(Path.of("/sys/class/thermal/thermal_zone0/temp")).trim()) / 1000D; + } catch (IOException e) { + return -1; + } + } + + @Override + public AutoUpdateStrategyProvider getType() { + return StandardUpdateStrategyProvider.CPU; + } +} diff --git a/src/fr/uca/iut/clfreville2/model/sensor/auto/RandomUpdateStrategy.java b/src/fr/uca/iut/clfreville2/model/sensor/auto/RandomUpdateStrategy.java new file mode 100644 index 0000000..526b629 --- /dev/null +++ b/src/fr/uca/iut/clfreville2/model/sensor/auto/RandomUpdateStrategy.java @@ -0,0 +1,34 @@ +package fr.uca.iut.clfreville2.model.sensor.auto; + +import fr.uca.iut.clfreville2.model.sensor.AutoSensor; +import fr.uca.iut.clfreville2.model.sensor.auto.provider.AutoUpdateStrategyProvider; +import fr.uca.iut.clfreville2.model.sensor.auto.provider.StandardUpdateStrategyProvider; + +import java.util.Random; + +public class RandomUpdateStrategy implements AutoUpdateStrategy { + + private final Random random; + private final int min; + private final int max; + + public RandomUpdateStrategy(int min, int max) { + this(new Random(), min, max); + } + + public RandomUpdateStrategy(Random random, int min, int max) { + this.random = random; + this.min = min; + this.max = max; + } + + @Override + public double nextValue(AutoSensor currentState) { + return random.nextDouble(min, max); + } + + @Override + public AutoUpdateStrategyProvider getType() { + return StandardUpdateStrategyProvider.RANDOM_UPDATE; + } +} diff --git a/src/fr/uca/iut/clfreville2/model/sensor/auto/RandomVariationStrategy.java b/src/fr/uca/iut/clfreville2/model/sensor/auto/RandomVariationStrategy.java index 140243f..1d9e6ef 100644 --- a/src/fr/uca/iut/clfreville2/model/sensor/auto/RandomVariationStrategy.java +++ b/src/fr/uca/iut/clfreville2/model/sensor/auto/RandomVariationStrategy.java @@ -1,6 +1,8 @@ package fr.uca.iut.clfreville2.model.sensor.auto; import fr.uca.iut.clfreville2.model.sensor.AutoSensor; +import fr.uca.iut.clfreville2.model.sensor.auto.provider.AutoUpdateStrategyProvider; +import fr.uca.iut.clfreville2.model.sensor.auto.provider.StandardUpdateStrategyProvider; import java.util.Random; @@ -22,4 +24,9 @@ public class RandomVariationStrategy implements AutoUpdateStrategy { public double nextValue(AutoSensor currentState) { return currentState.getTemperature() + random.nextInt(maxVariation * 2) - maxVariation; } + + @Override + public AutoUpdateStrategyProvider getType() { + return StandardUpdateStrategyProvider.RANDOM_VARIATION; + } } diff --git a/src/fr/uca/iut/clfreville2/model/sensor/auto/provider/AutoUpdateStrategyProvider.java b/src/fr/uca/iut/clfreville2/model/sensor/auto/provider/AutoUpdateStrategyProvider.java new file mode 100644 index 0000000..4f3b626 --- /dev/null +++ b/src/fr/uca/iut/clfreville2/model/sensor/auto/provider/AutoUpdateStrategyProvider.java @@ -0,0 +1,9 @@ +package fr.uca.iut.clfreville2.model.sensor.auto.provider; + +import fr.uca.iut.clfreville2.model.sensor.auto.AutoUpdateStrategy; +import fr.uca.iut.clfreville2.model.shared.Nameable; + +public interface AutoUpdateStrategyProvider extends Nameable { + + AutoUpdateStrategy create(); +} diff --git a/src/fr/uca/iut/clfreville2/model/sensor/auto/provider/StandardUpdateStrategyProvider.java b/src/fr/uca/iut/clfreville2/model/sensor/auto/provider/StandardUpdateStrategyProvider.java new file mode 100644 index 0000000..3e071c8 --- /dev/null +++ b/src/fr/uca/iut/clfreville2/model/sensor/auto/provider/StandardUpdateStrategyProvider.java @@ -0,0 +1,47 @@ +package fr.uca.iut.clfreville2.model.sensor.auto.provider; + +import fr.uca.iut.clfreville2.model.sensor.auto.AutoUpdateStrategy; +import fr.uca.iut.clfreville2.model.sensor.auto.CpuUpdateStrategy; +import fr.uca.iut.clfreville2.model.sensor.auto.RandomUpdateStrategy; +import fr.uca.iut.clfreville2.model.sensor.auto.RandomVariationStrategy; + +/** + * Provide common update strategies. + *

+ * This enum ensures that the same strategy is always returned with the same identity. + */ +public enum StandardUpdateStrategyProvider implements AutoUpdateStrategyProvider { + RANDOM_UPDATE { + @Override + public AutoUpdateStrategy create() { + return new RandomUpdateStrategy(-10, 40); + } + + @Override + public String getName() { + return "Random"; + } + }, + RANDOM_VARIATION { + @Override + public AutoUpdateStrategy create() { + return new RandomVariationStrategy(5); + } + + @Override + public String getName() { + return "Random variation"; + } + }, + CPU { + @Override + public AutoUpdateStrategy create() { + return new CpuUpdateStrategy(); + } + + @Override + public String getName() { + return "CPU"; + } + } +}