Mqtt added, changed MVC to MVVM hybrid architecture
This commit is contained in:
parent
b777e4c817
commit
411033e6b8
5
pom.xml
5
pom.xml
@ -26,6 +26,11 @@
|
|||||||
<version>2.1.0</version>
|
<version>2.1.0</version>
|
||||||
<type>jar</type>
|
<type>jar</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.paho</groupId>
|
||||||
|
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||||
|
<version>1.2.5</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
package efi.projekt.gesundheitsassistent;
|
package efi.projekt.gesundheitsassistent;
|
||||||
|
|
||||||
import atlantafx.base.theme.NordDark;
|
import atlantafx.base.theme.Dracula;
|
||||||
import efi.projekt.gesundheitsassistent.controller.MetadataDialogController;
|
import efi.projekt.gesundheitsassistent.model.FxModel;
|
||||||
import efi.projekt.gesundheitsassistent.model.Metadata;
|
import efi.projekt.gesundheitsassistent.controller.FxViewController;
|
||||||
|
import efi.projekt.gesundheitsassistent.viewmodel.FxViewModel;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Parent;
|
import javafx.scene.Parent;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.stage.Modality;
|
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -19,48 +19,29 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public class FxStart extends Application {
|
public class FxStart extends Application {
|
||||||
|
|
||||||
private static Scene scene;
|
|
||||||
private Metadata metadata; // das zentrale Model
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage primaryStage) throws IOException {
|
public void start(Stage primaryStage) throws IOException {
|
||||||
|
// Lade FXML
|
||||||
|
FXMLLoader loader = new FXMLLoader(getClass().getResource("/efi/projekt/gesundheitsassistent/view/FxView.fxml"));
|
||||||
|
Parent root = loader.load();
|
||||||
|
|
||||||
// 1️⃣ Metadata Model erzeugen
|
FxViewController controller = loader.getController();
|
||||||
metadata = new Metadata();
|
|
||||||
|
|
||||||
// 2️⃣ Metadata Dialog laden
|
// Erzeuge Model & ViewModel
|
||||||
FXMLLoader dialogLoader = new FXMLLoader(getClass()
|
FxModel model = new FxModel();
|
||||||
.getResource("/efi/projekt/gesundheitsassistent/view/MetadataDialog.fxml"));
|
FxViewModel viewModel = new FxViewModel(model);
|
||||||
Parent dialogRoot = dialogLoader.load();
|
|
||||||
|
|
||||||
// Controller bekommen und Model übergeben
|
// Verbinde Controller mit ViewModel
|
||||||
MetadataDialogController dialogController = dialogLoader.getController();
|
controller.setViewModel(viewModel);
|
||||||
dialogController.setMetadata(metadata);
|
|
||||||
|
|
||||||
// 3️⃣ Dialog Stage erzeugen
|
Scene scene = new Scene(root, 1280, 720);
|
||||||
Stage dialogStage = new Stage();
|
Application.setUserAgentStylesheet(new Dracula().getUserAgentStylesheet());
|
||||||
dialogStage.setTitle("Metadaten eingeben");
|
|
||||||
dialogStage.initModality(Modality.APPLICATION_MODAL); // blockiert Hauptfenster
|
|
||||||
dialogStage.setScene(new Scene(dialogRoot));
|
|
||||||
dialogStage.showAndWait(); // wartet bis Dialog geschlossen wird
|
|
||||||
|
|
||||||
// 4️⃣ Hauptfenster laden
|
|
||||||
FXMLLoader mainLoader = new FXMLLoader(getClass()
|
|
||||||
.getResource("/efi/projekt/gesundheitsassistent/view/FxView.fxml"));
|
|
||||||
Parent mainRoot = mainLoader.load();
|
|
||||||
|
|
||||||
scene = new Scene(mainRoot, 1280, 720);
|
|
||||||
Application.setUserAgentStylesheet(new NordDark().getUserAgentStylesheet());
|
|
||||||
|
|
||||||
primaryStage.setTitle("Virtueller Gesundheitsassistent");
|
primaryStage.setTitle("Virtueller Gesundheitsassistent");
|
||||||
primaryStage.setScene(scene);
|
primaryStage.setScene(scene);
|
||||||
primaryStage.show();
|
primaryStage.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setRoot(String fxml) throws IOException {
|
|
||||||
scene.setRoot(loadFXML(fxml));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Parent loadFXML(String fxml) throws IOException {
|
private static Parent loadFXML(String fxml) throws IOException {
|
||||||
FXMLLoader fxmlLoader = new FXMLLoader(
|
FXMLLoader fxmlLoader = new FXMLLoader(
|
||||||
FxStart.class.getResource("/efi/projekt/gesundheitsassistent/view/" + fxml + ".fxml")
|
FxStart.class.getResource("/efi/projekt/gesundheitsassistent/view/" + fxml + ".fxml")
|
||||||
@ -71,8 +52,4 @@ public class FxStart extends Application {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
launch();
|
launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Metadata getMetadata() {
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,13 +5,23 @@
|
|||||||
package efi.projekt.gesundheitsassistent.controller;
|
package efi.projekt.gesundheitsassistent.controller;
|
||||||
|
|
||||||
import efi.projekt.gesundheitsassistent.model.FxModel;
|
import efi.projekt.gesundheitsassistent.model.FxModel;
|
||||||
|
import efi.projekt.gesundheitsassistent.model.Metadata;
|
||||||
|
import efi.projekt.gesundheitsassistent.viewmodel.FxViewModel;
|
||||||
|
import efi.projekt.gesundheitsassistent.viewmodel.MetadataDialogViewModel;
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
|
import javafx.scene.Parent;
|
||||||
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.ButtonType;
|
import javafx.scene.control.ButtonType;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.stage.Modality;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FXML Controller class
|
* FXML Controller class
|
||||||
@ -20,17 +30,27 @@ import javafx.scene.control.ButtonType;
|
|||||||
*/
|
*/
|
||||||
public class FxViewController implements Initializable {
|
public class FxViewController implements Initializable {
|
||||||
|
|
||||||
private FxModel model;
|
private FxViewModel viewModel;
|
||||||
|
|
||||||
@FXML
|
@FXML private Button exitButton;
|
||||||
private Button exitButton;
|
@FXML private TextField messageInputField;
|
||||||
|
@FXML private TextField messageOutputField;
|
||||||
|
@FXML private Button sendButton;
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the controller class.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL url, ResourceBundle rb) {
|
public void initialize(URL url, ResourceBundle rb) {
|
||||||
|
exitButton.setOnAction(e -> handleExit());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViewModel(FxViewModel viewModel) {
|
||||||
|
this.viewModel = viewModel;
|
||||||
|
initBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initBindings() {
|
||||||
|
//Bindings: View <-> ViewModel
|
||||||
|
messageInputField.textProperty().bindBidirectional(viewModel.outgoingMessageProperty());
|
||||||
|
messageOutputField.textProperty().bindBidirectional(viewModel.incomingMessageProperty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@ -39,10 +59,30 @@ public class FxViewController implements Initializable {
|
|||||||
alert.showAndWait()
|
alert.showAndWait()
|
||||||
.filter(response -> response == ButtonType.OK)
|
.filter(response -> response == ButtonType.OK)
|
||||||
.ifPresent(response -> System.exit(0));
|
.ifPresent(response -> System.exit(0));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setModel(FxModel model) {
|
@FXML
|
||||||
this.model = model;
|
private void handleSendMessage() {
|
||||||
|
viewModel.sendMessage(messageInputField.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void handleOptions() throws IOException {
|
||||||
|
// Dialog
|
||||||
|
FXMLLoader loader = new FXMLLoader(getClass()
|
||||||
|
.getResource("/efi/projekt/gesundheitsassistent/view/MetadataDialog.fxml"));
|
||||||
|
Parent dialogRoot = loader.load();
|
||||||
|
|
||||||
|
// ViewModel erzeugen
|
||||||
|
Metadata metadata = new Metadata();
|
||||||
|
loader.<MetadataDialogController>getController().setViewModel(
|
||||||
|
new MetadataDialogViewModel(metadata)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Dialog Stage erzeugen
|
||||||
|
Stage dialogStage = new Stage();
|
||||||
|
dialogStage.initModality(Modality.APPLICATION_MODAL);
|
||||||
|
dialogStage.setScene(new Scene(dialogRoot));
|
||||||
|
dialogStage.showAndWait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,12 +5,14 @@
|
|||||||
package efi.projekt.gesundheitsassistent.controller;
|
package efi.projekt.gesundheitsassistent.controller;
|
||||||
|
|
||||||
import efi.projekt.gesundheitsassistent.model.Metadata;
|
import efi.projekt.gesundheitsassistent.model.Metadata;
|
||||||
|
import efi.projekt.gesundheitsassistent.viewmodel.MetadataDialogViewModel;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.ButtonType;
|
import javafx.scene.control.ButtonType;
|
||||||
import javafx.scene.control.ChoiceBox;
|
import javafx.scene.control.ChoiceBox;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
import javafx.util.converter.NumberStringConverter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -18,59 +20,39 @@ import javafx.stage.Stage;
|
|||||||
*/
|
*/
|
||||||
public class MetadataDialogController {
|
public class MetadataDialogController {
|
||||||
|
|
||||||
@FXML
|
@FXML private TextField nameField;
|
||||||
private TextField nameField;
|
@FXML private TextField ageField;
|
||||||
|
@FXML private ChoiceBox<String> genderChoiceBox;
|
||||||
|
@FXML private TextField heightField;
|
||||||
|
@FXML private TextField weightField;
|
||||||
|
|
||||||
@FXML
|
private MetadataDialogViewModel viewModel;
|
||||||
private TextField ageField;
|
|
||||||
|
|
||||||
@FXML
|
public void setViewModel(MetadataDialogViewModel viewModel) {
|
||||||
private ChoiceBox<String> genderChoiceBox;
|
this.viewModel = viewModel;
|
||||||
|
|
||||||
@FXML
|
|
||||||
private TextField heightField;
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private TextField weightField;
|
|
||||||
|
|
||||||
private Metadata metadata;
|
|
||||||
|
|
||||||
public void initialize() {
|
|
||||||
// ChoiceBox füllen
|
|
||||||
genderChoiceBox.getItems().addAll("Männlich", "Weiblich", "Divers");
|
genderChoiceBox.getItems().addAll("Männlich", "Weiblich", "Divers");
|
||||||
genderChoiceBox.setValue("Männlich"); // default
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMetadata(Metadata metadata) {
|
// Bindings
|
||||||
this.metadata = metadata;
|
nameField.textProperty().bindBidirectional(viewModel.nameProperty());
|
||||||
bindFields();
|
ageField.textProperty().bindBidirectional(viewModel.ageProperty(), new NumberStringConverter());
|
||||||
}
|
genderChoiceBox.valueProperty().bindBidirectional(viewModel.genderProperty());
|
||||||
|
heightField.textProperty().bindBidirectional(viewModel.heightProperty(), new NumberStringConverter());
|
||||||
private void bindFields() {
|
weightField.textProperty().bindBidirectional(viewModel.weightProperty(), new NumberStringConverter());
|
||||||
// Bidirektionales Binding zwischen Model und UI
|
|
||||||
nameField.textProperty().bindBidirectional(metadata.nameProperty());
|
|
||||||
ageField.textProperty().bindBidirectional(metadata.ageProperty(), new javafx.util.converter.NumberStringConverter());
|
|
||||||
genderChoiceBox.valueProperty().bindBidirectional(metadata.genderProperty());
|
|
||||||
heightField.textProperty().bindBidirectional(metadata.heightProperty(), new javafx.util.converter.NumberStringConverter());
|
|
||||||
weightField.textProperty().bindBidirectional(metadata.weightProperty(), new javafx.util.converter.NumberStringConverter());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void handleOk() {
|
private void handleOk() {
|
||||||
try {
|
try {
|
||||||
metadata.validate();
|
viewModel.save();
|
||||||
// Dialog schließen
|
((Stage) nameField.getScene().getWindow()).close();
|
||||||
Stage stage = (Stage) nameField.getScene().getWindow();
|
|
||||||
stage.close();
|
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
Alert alert = new Alert(Alert.AlertType.ERROR, e.getMessage(), ButtonType.OK);
|
new Alert(Alert.AlertType.ERROR, e.getMessage(), ButtonType.OK).showAndWait();
|
||||||
alert.showAndWait();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void handleCancel() {
|
private void handleCancel() {
|
||||||
Stage stage = (Stage) nameField.getScene().getWindow();
|
((Stage) nameField.getScene().getWindow()).close();
|
||||||
stage.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import javafx.beans.property.StringProperty;
|
|||||||
public class FxModel implements Serializable {
|
public class FxModel implements Serializable {
|
||||||
|
|
||||||
private final StringProperty id = new SimpleStringProperty(this, "id");
|
private final StringProperty id = new SimpleStringProperty(this, "id");
|
||||||
|
private MqttJavaClient mqttClient = new MqttJavaClient();
|
||||||
|
|
||||||
public FxModel() {}
|
public FxModel() {}
|
||||||
|
|
||||||
@ -33,5 +34,16 @@ public class FxModel implements Serializable {
|
|||||||
public void validate() throws IllegalArgumentException {
|
public void validate() throws IllegalArgumentException {
|
||||||
// Subklassen können überschreiben
|
// Subklassen können überschreiben
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void publishMessage(String topic, String messageContent, int qos) {
|
||||||
|
getMqttClient().publishMessage(topic, messageContent, qos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the mqttClient
|
||||||
|
*/
|
||||||
|
public MqttJavaClient getMqttClient() {
|
||||||
|
return mqttClient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
|
||||||
|
*/
|
||||||
|
package efi.projekt.gesundheitsassistent.model;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttCallback;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||||
|
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author aumni
|
||||||
|
*/
|
||||||
|
public class MqttJavaClient implements MqttCallback {
|
||||||
|
|
||||||
|
private Map<String, Consumer<String>> topicListeners = new HashMap<>();
|
||||||
|
|
||||||
|
private static final String BROKER_URL = "tcp://localhost:1883";
|
||||||
|
private static final String CLIENT_ID = "JavaClientPublisherSubscriber";
|
||||||
|
private static final String PUBLISH_TOPIC = "temperatur";
|
||||||
|
private static final String SUBSCRIBE_TOPIC = "Text";
|
||||||
|
|
||||||
|
private MqttClient client;
|
||||||
|
|
||||||
|
public MqttJavaClient() {
|
||||||
|
try {
|
||||||
|
client = new MqttClient(BROKER_URL, CLIENT_ID, new MemoryPersistence());
|
||||||
|
client.setCallback(this);
|
||||||
|
|
||||||
|
MqttConnectOptions options = new MqttConnectOptions();
|
||||||
|
options.setCleanSession(true);
|
||||||
|
options.setAutomaticReconnect(true);
|
||||||
|
|
||||||
|
System.out.println("Verbinde mit Broker..." + BROKER_URL);
|
||||||
|
client.connect(options);
|
||||||
|
System.out.println("Verbunden");
|
||||||
|
|
||||||
|
System.out.println("Abonniere Topic: " + SUBSCRIBE_TOPIC);
|
||||||
|
client.subscribe(SUBSCRIBE_TOPIC);
|
||||||
|
System.out.println("Topic abonniert!");
|
||||||
|
|
||||||
|
} catch (MqttException ex) {
|
||||||
|
System.err.println("Fehler beim Initialisieren oder Verbinden: " + ex.getMessage());
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTopicListeners(String topic, Consumer<String> listener) {
|
||||||
|
topicListeners.put(topic, listener);
|
||||||
|
try {
|
||||||
|
client.subscribe(topic);
|
||||||
|
System.out.println("Abonniert: " + topic);
|
||||||
|
} catch (MqttException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void publishMessage(String topic, String message, int qos) {
|
||||||
|
try {
|
||||||
|
MqttMessage msg = new MqttMessage(message.getBytes());
|
||||||
|
msg.setQos(qos);
|
||||||
|
client.publish(topic, msg);
|
||||||
|
System.out.println("Nachricht veröffentlicht: Topic = " + topic + ", Inhalt = " + message + ", QoS = " + qos);
|
||||||
|
} catch (MqttException ex) {
|
||||||
|
System.err.println("Fehler beim Veröffentlicher der Nachricht: " + ex.getMessage());
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connectionLost(Throwable cause) {
|
||||||
|
System.out.println("Verbindung zum Broker verloren! Ursache: " + cause.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void messageArrived(String topic, MqttMessage message) throws Exception {
|
||||||
|
String payload = new String(message.getPayload());
|
||||||
|
|
||||||
|
System.out.println("Nachricht emmpfangen:");
|
||||||
|
System.out.println(" Topic: " + topic);
|
||||||
|
System.out.println(" Inhalt: " + new String(message.getPayload()));
|
||||||
|
System.out.println(" QoS: " + message.getQos());
|
||||||
|
|
||||||
|
Consumer<String> listener = topicListeners.get(topic);
|
||||||
|
if (listener != null) {
|
||||||
|
listener.accept(payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deliveryComplete(IMqttDeliveryToken token) {
|
||||||
|
System.out.println("Nachricht erfolgreich zugestellt (QoS > 0). Token: " + token.getMessageId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
|
||||||
|
*/
|
||||||
|
package efi.projekt.gesundheitsassistent.viewmodel;
|
||||||
|
|
||||||
|
import efi.projekt.gesundheitsassistent.model.FxModel;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author naumueller
|
||||||
|
*/
|
||||||
|
public class FxViewModel {
|
||||||
|
|
||||||
|
private final FxModel model;
|
||||||
|
private Map<String, StringProperty> topicMessages = new HashMap<>();
|
||||||
|
private final StringProperty incomingMessage = new SimpleStringProperty("");
|
||||||
|
private final StringProperty outgoingMessage = new SimpleStringProperty("");
|
||||||
|
|
||||||
|
private final StringProperty messageToSend = new SimpleStringProperty("");
|
||||||
|
|
||||||
|
public FxViewModel(FxModel model) {
|
||||||
|
this.model = model;
|
||||||
|
|
||||||
|
subscribeTopic("Text");
|
||||||
|
subscribeTopic("Temperatur");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void subscribeTopic(String topic) {
|
||||||
|
model.getMqttClient().addTopicListeners(topic, msg -> {
|
||||||
|
Platform.runLater(() -> getTopicProperty(topic).set(msg));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendMessage(String msg) {
|
||||||
|
if (msg != null && !msg.isBlank()) {
|
||||||
|
model.getMqttClient().publishMessage("Text", msg, 1);
|
||||||
|
outgoingMessage.set("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty incomingMessageProperty() { return incomingMessage; }
|
||||||
|
public StringProperty outgoingMessageProperty() { return outgoingMessage; }
|
||||||
|
public StringProperty getTopicProperty(String topic) { return topicMessages.computeIfAbsent(topic, t -> new SimpleStringProperty()); }
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||||||
|
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
|
||||||
|
*/
|
||||||
|
package efi.projekt.gesundheitsassistent.viewmodel;
|
||||||
|
|
||||||
|
import efi.projekt.gesundheitsassistent.model.Metadata;
|
||||||
|
import javafx.beans.property.DoubleProperty;
|
||||||
|
import javafx.beans.property.IntegerProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author naumueller
|
||||||
|
*/
|
||||||
|
public class MetadataDialogViewModel {
|
||||||
|
|
||||||
|
private final Metadata metadata;
|
||||||
|
|
||||||
|
public MetadataDialogViewModel(Metadata metadata) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty nameProperty() { return metadata.nameProperty(); }
|
||||||
|
public IntegerProperty ageProperty() { return metadata.ageProperty(); }
|
||||||
|
public StringProperty genderProperty() { return metadata.genderProperty(); }
|
||||||
|
public DoubleProperty heightProperty() { return metadata.heightProperty(); }
|
||||||
|
public DoubleProperty weightProperty() { return metadata.weightProperty(); }
|
||||||
|
|
||||||
|
public void save() {
|
||||||
|
metadata.validate();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ module efi.projekt.gesundheitsassistent {
|
|||||||
requires javafx.fxml;
|
requires javafx.fxml;
|
||||||
requires java.base;
|
requires java.base;
|
||||||
requires atlantafx.base;
|
requires atlantafx.base;
|
||||||
|
requires org.eclipse.paho.client.mqttv3;
|
||||||
|
|
||||||
opens efi.projekt.gesundheitsassistent to javafx.fxml;
|
opens efi.projekt.gesundheitsassistent to javafx.fxml;
|
||||||
opens efi.projekt.gesundheitsassistent.controller to javafx.fxml;
|
opens efi.projekt.gesundheitsassistent.controller to javafx.fxml;
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 467 B |
Binary file not shown.
|
After Width: | Height: | Size: 633 KiB |
@ -3,7 +3,10 @@
|
|||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.Button?>
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.control.TextField?>
|
||||||
<?import javafx.scene.control.TitledPane?>
|
<?import javafx.scene.control.TitledPane?>
|
||||||
|
<?import javafx.scene.image.Image?>
|
||||||
|
<?import javafx.scene.image.ImageView?>
|
||||||
<?import javafx.scene.layout.BorderPane?>
|
<?import javafx.scene.layout.BorderPane?>
|
||||||
<?import javafx.scene.layout.HBox?>
|
<?import javafx.scene.layout.HBox?>
|
||||||
<?import javafx.scene.layout.StackPane?>
|
<?import javafx.scene.layout.StackPane?>
|
||||||
@ -18,7 +21,7 @@
|
|||||||
<Insets bottom="15" left="15" right="15" top="15" />
|
<Insets bottom="15" left="15" right="15" top="15" />
|
||||||
</padding>
|
</padding>
|
||||||
<Label text="Virtueller Gesundheitsassistent" />
|
<Label text="Virtueller Gesundheitsassistent" />
|
||||||
<Button text="Einstellungen" />
|
<Button onMouseClicked="#handleOptions" text="Einstellungen" />
|
||||||
</HBox>
|
</HBox>
|
||||||
</top>
|
</top>
|
||||||
|
|
||||||
@ -29,7 +32,7 @@
|
|||||||
<Insets bottom="15" left="15" right="15" top="15" />
|
<Insets bottom="15" left="15" right="15" top="15" />
|
||||||
</padding>
|
</padding>
|
||||||
<!-- Linke Seite: Gesundheitsdaten -->
|
<!-- Linke Seite: Gesundheitsdaten -->
|
||||||
<VBox alignment="CENTER" spacing="15" HBox.hgrow="ALWAYS">
|
<!--<VBox alignment="CENTER" spacing="15" HBox.hgrow="ALWAYS">
|
||||||
<TitledPane text="Gesundheitsdaten">
|
<TitledPane text="Gesundheitsdaten">
|
||||||
<content>
|
<content>
|
||||||
<VBox spacing="10">
|
<VBox spacing="10">
|
||||||
@ -42,6 +45,46 @@
|
|||||||
</VBox>
|
</VBox>
|
||||||
</content>
|
</content>
|
||||||
</TitledPane>
|
</TitledPane>
|
||||||
|
</VBox>-->
|
||||||
|
|
||||||
|
<VBox alignment="CENTER" spacing="15" HBox.hgrow="ALWAYS">
|
||||||
|
<TitledPane text="Gesundheitsdaten">
|
||||||
|
<content>
|
||||||
|
<VBox spacing="10">
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="10" left="10" right="10" top="10" />
|
||||||
|
</padding>
|
||||||
|
|
||||||
|
<!-- Herzfrequenz -->
|
||||||
|
<HBox alignment="CENTER_LEFT" spacing="10">
|
||||||
|
<ImageView fitHeight="24" fitWidth="24" pickOnBounds="true" preserveRatio="true">
|
||||||
|
<image>
|
||||||
|
<Image url="@../icons/icons8-health-48.png" />
|
||||||
|
</image></ImageView>
|
||||||
|
<Label text="Herzfrequenz: 72 bpm" />
|
||||||
|
</HBox>
|
||||||
|
|
||||||
|
<!-- Temperatur -->
|
||||||
|
<HBox alignment="CENTER_LEFT" spacing="10">
|
||||||
|
<ImageView fitHeight="24" fitWidth="24" pickOnBounds="true" preserveRatio="true">
|
||||||
|
<image>
|
||||||
|
<Image url="@../icons/icons8-temperature-48.png" />
|
||||||
|
</image></ImageView>
|
||||||
|
<Label text="Temperatur: 36.8 °C" />
|
||||||
|
</HBox>
|
||||||
|
|
||||||
|
<!-- Stress-Level -->
|
||||||
|
<HBox alignment="CENTER_LEFT" spacing="10">
|
||||||
|
<ImageView fitHeight="24" fitWidth="24" pickOnBounds="true" preserveRatio="true">
|
||||||
|
<image>
|
||||||
|
<Image url="@../icons/icons8-stress-64.png" />
|
||||||
|
</image></ImageView>
|
||||||
|
<Label text="Stress-Level: Niedrig" />
|
||||||
|
</HBox>
|
||||||
|
|
||||||
|
</VBox>
|
||||||
|
</content>
|
||||||
|
</TitledPane>
|
||||||
</VBox>
|
</VBox>
|
||||||
|
|
||||||
<!-- Rechte Seite: Avatar -->
|
<!-- Rechte Seite: Avatar -->
|
||||||
@ -49,9 +92,18 @@
|
|||||||
<TitledPane text="Avatar">
|
<TitledPane text="Avatar">
|
||||||
<content>
|
<content>
|
||||||
<StackPane fx:id="avatarContainer" alignment="CENTER" prefHeight="400" prefWidth="400">
|
<StackPane fx:id="avatarContainer" alignment="CENTER" prefHeight="400" prefWidth="400">
|
||||||
<Label text="3D-Avatar wird geladen..." textFill="white" />
|
<HBox alignment="CENTER" spacing="10">
|
||||||
|
<ImageView fitHeight="300.0" fitWidth="300.0" pickOnBounds="true" preserveRatio="true">
|
||||||
|
<image>
|
||||||
|
<Image url="@../icons/icons8-account-male.gif" />
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</HBox>
|
||||||
</StackPane>
|
</StackPane>
|
||||||
</content>
|
</content>
|
||||||
|
<graphic>
|
||||||
|
<Label text="3D-Avatar wird geladen..." textFill="white" />
|
||||||
|
</graphic>
|
||||||
</TitledPane>
|
</TitledPane>
|
||||||
</VBox>
|
</VBox>
|
||||||
</HBox>
|
</HBox>
|
||||||
@ -63,7 +115,10 @@
|
|||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="15" left="15" right="15" top="15" />
|
<Insets bottom="15" left="15" right="15" top="15" />
|
||||||
</padding>
|
</padding>
|
||||||
<Button onMouseClicked="#handleExit" text="Beenden" />
|
<Button fx:id="sendButton" mnemonicParsing="false" onMouseClicked="#handleSendMessage" text="Send message" />
|
||||||
|
<TextField fx:id="messageInputField" />
|
||||||
|
<TextField fx:id="messageOutputField" editable="false" />
|
||||||
|
<Button fx:id="exitButton" onMouseClicked="#handleExit" text="Beenden" />
|
||||||
</HBox>
|
</HBox>
|
||||||
</bottom>
|
</bottom>
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user