Compare commits
No commits in common. "de38f446fed90ba16c01071d35b4a37b9047ca65" and "5b072329d32b3357379f809c350e3c4e23f705ce" have entirely different histories.
de38f446fe
...
5b072329d3
18
README.md
18
README.md
@ -1,18 +0,0 @@
|
|||||||
Virtueller Gesundheitsassistent
|
|
||||||
Überblick
|
|
||||||
Dieses Projekt implementiert einen virtuellen Gesundheits- und Fahrassistenten
|
|
||||||
auf Basis von JavaFX. Die Anwendung visualisiert den aktuellen Zustand des
|
|
||||||
Fahrers (z.B. Müdigkeit, Ablenkung, Stress) und integriert:
|
|
||||||
- ein ML-Modell, das Zustände klassifiziert
|
|
||||||
- eine JavaFX-GUI mit mehreren Designvarianten
|
|
||||||
- OpenCV für Kamera-Preview
|
|
||||||
- Unreal Engine Pixel Streaming für einen sprechenden Avatar
|
|
||||||
- WebSocket-Kommunikation zur Steuerung des Avatars
|
|
||||||
|
|
||||||
Features
|
|
||||||
Architektur
|
|
||||||
Services
|
|
||||||
Views & UI-Struktur
|
|
||||||
Java-Version & Build
|
|
||||||
MQTT & Datenfluss
|
|
||||||
OpenCV
|
|
||||||
5
pom.xml
5
pom.xml
@ -43,11 +43,6 @@
|
|||||||
<version>4.12.0</version>
|
<version>4.12.0</version>
|
||||||
<type>jar</type>
|
<type>jar</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.xerial</groupId>
|
|
||||||
<artifactId>sqlite-jdbc</artifactId>
|
|
||||||
<version>3.51.1.0</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|||||||
@ -1,11 +1,5 @@
|
|||||||
package efi.projekt.virtueller_gesundheitsassistent;
|
package efi.projekt.virtueller_gesundheitsassistent;
|
||||||
|
|
||||||
import efi.projekt.virtueller_gesundheitsassistent.model.AppState;
|
|
||||||
import efi.projekt.virtueller_gesundheitsassistent.service.DataPersistenceService;
|
|
||||||
import efi.projekt.virtueller_gesundheitsassistent.service.EvaluationService;
|
|
||||||
import efi.projekt.virtueller_gesundheitsassistent.service.MqttClientService;
|
|
||||||
import efi.projekt.virtueller_gesundheitsassistent.service.StatisticsService;
|
|
||||||
import efi.projekt.virtueller_gesundheitsassistent.service.UnrealWebSocketService;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import static javafx.application.Application.launch;
|
import static javafx.application.Application.launch;
|
||||||
@ -21,50 +15,15 @@ import javafx.stage.Stage;
|
|||||||
*/
|
*/
|
||||||
public class App extends Application {
|
public class App extends Application {
|
||||||
|
|
||||||
private final AppState appState = new AppState();
|
|
||||||
|
|
||||||
// Services
|
|
||||||
private DataPersistenceService persistenceService;
|
|
||||||
private StatisticsService statisticsService;
|
|
||||||
private EvaluationService evaluationService;
|
|
||||||
private UnrealWebSocketService unrealService;
|
|
||||||
private MqttClientService mqttService;
|
|
||||||
|
|
||||||
@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/virtueller_gesundheitsassistent/view/FxView.fxml"));
|
||||||
|
Parent root = loader.load();
|
||||||
|
|
||||||
// =========================
|
// Erzeuge Model & ViewModel
|
||||||
// Services initialisieren
|
|
||||||
// =========================
|
|
||||||
|
|
||||||
// Unreal-WebService
|
|
||||||
unrealService = new UnrealWebSocketService("127.0.0.1");
|
|
||||||
|
|
||||||
// MQTT-Service
|
Scene scene = new Scene(root, 1280, 720);
|
||||||
mqttService = new MqttClientService();
|
|
||||||
|
|
||||||
// Datenbank initialisieren
|
|
||||||
persistenceService = new DataPersistenceService();
|
|
||||||
|
|
||||||
// Statistik-Service
|
|
||||||
statisticsService = new StatisticsService();
|
|
||||||
|
|
||||||
// Evaluationsservice
|
|
||||||
evaluationService = new EvaluationService(statisticsService, appState, unrealService);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =========================
|
|
||||||
// UI laden
|
|
||||||
// =========================
|
|
||||||
|
|
||||||
FXMLLoader loader = new FXMLLoader(
|
|
||||||
getClass().getResource(
|
|
||||||
"/efi/projekt/virtueller_gesundheitsassistent/view/MainView.fxml"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
Scene scene = new Scene(loader.load(), 1400, 900);
|
|
||||||
|
|
||||||
primaryStage.setTitle("Virtueller Gesundheitsassistent");
|
primaryStage.setTitle("Virtueller Gesundheitsassistent");
|
||||||
primaryStage.setScene(scene);
|
primaryStage.setScene(scene);
|
||||||
@ -79,6 +38,7 @@ public class App extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
launch(args);
|
launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,26 +0,0 @@
|
|||||||
package efi.projekt.virtueller_gesundheitsassistent.model;
|
|
||||||
|
|
||||||
import javafx.beans.property.ObjectProperty;
|
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author naumueller
|
|
||||||
*/
|
|
||||||
public class AppState {
|
|
||||||
|
|
||||||
private final ObjectProperty<ProblemLevel> problemLevel =
|
|
||||||
new SimpleObjectProperty<>(ProblemLevel.NONE);
|
|
||||||
|
|
||||||
public ObjectProperty<ProblemLevel> problemLevelProperty() {
|
|
||||||
return problemLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProblemLevel getProblemLevel() {
|
|
||||||
return problemLevel.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProblemLevel(ProblemLevel level) {
|
|
||||||
problemLevel.set(level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
package efi.projekt.virtueller_gesundheitsassistent.model;
|
||||||
|
|
||||||
|
import javafx.beans.property.BooleanProperty;
|
||||||
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author naumueller
|
||||||
|
*/
|
||||||
|
public class AssistantState {
|
||||||
|
|
||||||
|
private final ObjectProperty<ClassificationType> classification =
|
||||||
|
new SimpleObjectProperty<>(ClassificationType.NORMAL);
|
||||||
|
|
||||||
|
private final BooleanProperty speaking =
|
||||||
|
new SimpleBooleanProperty(false);
|
||||||
|
|
||||||
|
private final BooleanProperty monitoring =
|
||||||
|
new SimpleBooleanProperty(true);
|
||||||
|
|
||||||
|
public ObjectProperty<ClassificationType> classificationProperty() {
|
||||||
|
return classification;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanProperty speakingProperty() {
|
||||||
|
return speaking;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanProperty monitoringProperty() {
|
||||||
|
return monitoring;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package efi.projekt.virtueller_gesundheitsassistent.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author naumueller
|
||||||
|
*/
|
||||||
|
public enum ClassificationType {
|
||||||
|
NORMAL,
|
||||||
|
MUEDIGKEIT,
|
||||||
|
ABLENKUNG,
|
||||||
|
STRESS,
|
||||||
|
REAKTION
|
||||||
|
}
|
||||||
@ -1,12 +0,0 @@
|
|||||||
package efi.projekt.virtueller_gesundheitsassistent.model;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author naumueller
|
|
||||||
*/
|
|
||||||
public enum ProblemLevel {
|
|
||||||
NONE,
|
|
||||||
WARNING,
|
|
||||||
HIGH,
|
|
||||||
DISASTER
|
|
||||||
}
|
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package efi.projekt.virtueller_gesundheitsassistent.service;
|
||||||
|
|
||||||
|
import efi.projekt.virtueller_gesundheitsassistent.model.ClassificationType;
|
||||||
|
import efi.projekt.virtueller_gesundheitsassistent.util.Logger;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author naumueller
|
||||||
|
*/
|
||||||
|
public class ClassificationService {
|
||||||
|
|
||||||
|
private static final String TOPIC = "Text";
|
||||||
|
|
||||||
|
public ClassificationService(MqttClientService mqtt) {
|
||||||
|
|
||||||
|
mqtt.subscribe(TOPIC, payload -> {
|
||||||
|
|
||||||
|
ClassificationType type = switch (payload) {
|
||||||
|
case "0" -> ClassificationType.NORMAL;
|
||||||
|
case "1" -> ClassificationType.MUEDIGKEIT;
|
||||||
|
case "2" -> ClassificationType.ABLENKUNG;
|
||||||
|
case "3" -> ClassificationType.REAKTION;
|
||||||
|
case "4" -> ClassificationType.STRESS;
|
||||||
|
default -> ClassificationType.NORMAL;
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.info("STATE", "Neue Klassifizierung: " + type);
|
||||||
|
|
||||||
|
Platform.runLater(() ->
|
||||||
|
StateService.getState()
|
||||||
|
.classificationProperty()
|
||||||
|
.set(type)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.virtueller_gesundheitsassistent.service;
|
|
||||||
|
|
||||||
import efi.projekt.virtueller_gesundheitsassistent.util.Logger;
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.DriverManager;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Statement;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author naumueller
|
|
||||||
*/
|
|
||||||
public class DataPersistenceService {
|
|
||||||
|
|
||||||
private static final String DB_URL = "jdbc:sqlite:data/health.db";
|
|
||||||
|
|
||||||
public DataPersistenceService() {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
try (
|
|
||||||
Connection c = DriverManager.getConnection(DB_URL); Statement s = c.createStatement()) {
|
|
||||||
|
|
||||||
s.execute("""
|
|
||||||
CREATE TABLE IF NOT EXISTS binary_event (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
value INTEGER NOT NULL,
|
|
||||||
timestamp DATETIME NOT NULL
|
|
||||||
)
|
|
||||||
""");
|
|
||||||
|
|
||||||
Logger.info("DB", "Datenbank initialisiert");
|
|
||||||
|
|
||||||
} catch (SQLException e) {
|
|
||||||
Logger.error("DB", "Datenbank initialisierung fehlgeschlagen", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void store(int value) {
|
|
||||||
try (Connection c = DriverManager.getConnection(DB_URL); PreparedStatement ps = c.prepareStatement("INSERT INTO binary_event (value, timestamp) VALUES (?, ?)")) {
|
|
||||||
ps.setInt(1, value);
|
|
||||||
ps.setString(2, LocalDateTime.now().toString());
|
|
||||||
ps.executeUpdate();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
Logger.error("DB", "Database Insert fehlgeschlagen", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.virtueller_gesundheitsassistent.service;
|
|
||||||
|
|
||||||
import efi.projekt.virtueller_gesundheitsassistent.model.AppState;
|
|
||||||
import efi.projekt.virtueller_gesundheitsassistent.model.ProblemLevel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author naumueller
|
|
||||||
*/
|
|
||||||
public class EvaluationService {
|
|
||||||
|
|
||||||
private final StatisticsService statisticsService;
|
|
||||||
private final AppState appState;
|
|
||||||
private final UnrealWebSocketService unrealService;
|
|
||||||
|
|
||||||
public EvaluationService(
|
|
||||||
StatisticsService statisticsService,
|
|
||||||
AppState appState,
|
|
||||||
UnrealWebSocketService unrealService
|
|
||||||
) {
|
|
||||||
|
|
||||||
this.statisticsService = statisticsService;
|
|
||||||
this.appState = appState;
|
|
||||||
this.unrealService = unrealService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void evaluate() {
|
|
||||||
double ratio = statisticsService.getRatio(10);
|
|
||||||
|
|
||||||
ProblemLevel level;
|
|
||||||
|
|
||||||
if (ratio >= 0.9) {
|
|
||||||
level = ProblemLevel.DISASTER;
|
|
||||||
} else if (ratio >= 0.8) {
|
|
||||||
level = ProblemLevel.HIGH;
|
|
||||||
} else if (ratio >= 0.5) {
|
|
||||||
level = ProblemLevel.WARNING;
|
|
||||||
} else {
|
|
||||||
level = ProblemLevel.NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level != appState.getProblemLevel()) {
|
|
||||||
appState.setProblemLevel(level);
|
|
||||||
unrealService.speak(level.name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
package efi.projekt.virtueller_gesundheitsassistent.service;
|
package efi.projekt.virtueller_gesundheitsassistent.service;
|
||||||
|
|
||||||
import efi.projekt.virtueller_gesundheitsassistent.model.AppState;
|
import efi.projekt.virtueller_gesundheitsassistent.model.AssistantState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -8,11 +8,11 @@ import efi.projekt.virtueller_gesundheitsassistent.model.AppState;
|
|||||||
*/
|
*/
|
||||||
public class StateService {
|
public class StateService {
|
||||||
|
|
||||||
private static final AppState STATE = new AppState();
|
private static final AssistantState STATE = new AssistantState();
|
||||||
|
|
||||||
private StateService() {}
|
private StateService() {}
|
||||||
|
|
||||||
public static AppState getState() {
|
public static AssistantState getState() {
|
||||||
return STATE;
|
return STATE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.virtueller_gesundheitsassistent.service;
|
|
||||||
|
|
||||||
import efi.projekt.virtueller_gesundheitsassistent.util.Logger;
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.DriverManager;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author naumueller
|
|
||||||
*/
|
|
||||||
public class StatisticsService {
|
|
||||||
|
|
||||||
private static final String DB_URL = "jdbc:sqlite:data/health.db";
|
|
||||||
|
|
||||||
public double getRatio(int lastN) {
|
|
||||||
String query = """
|
|
||||||
SELECT AVG(value)
|
|
||||||
FROM (
|
|
||||||
SELECT value
|
|
||||||
FROM binary_event
|
|
||||||
ORDER BY timestamp DESC
|
|
||||||
LIMIT ?
|
|
||||||
)
|
|
||||||
""";
|
|
||||||
|
|
||||||
try (Connection c = DriverManager.getConnection(DB_URL); PreparedStatement ps = c.prepareStatement(query)) {
|
|
||||||
ps.setInt(1, lastN);
|
|
||||||
|
|
||||||
ResultSet rs = ps.executeQuery();
|
|
||||||
if (rs.next()) {
|
|
||||||
return rs.getDouble(1);
|
|
||||||
}
|
|
||||||
} catch (SQLException e) {
|
|
||||||
Logger.error("Evaluation", "Couldn't get ratio.", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -6,7 +6,6 @@ module efi.projekt.virtueller_gesundheitsassistent {
|
|||||||
requires javafx.web;
|
requires javafx.web;
|
||||||
requires jakarta.websocket.client;
|
requires jakarta.websocket.client;
|
||||||
requires opencv;
|
requires opencv;
|
||||||
requires java.sql;
|
|
||||||
|
|
||||||
|
|
||||||
opens efi.projekt.virtueller_gesundheitsassistent to javafx.fxml;
|
opens efi.projekt.virtueller_gesundheitsassistent to javafx.fxml;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user