ProgessLevelBar, ProcessManagement with SignallingServer

This commit is contained in:
Niklas Aumueller 2026-02-24 16:48:21 +01:00
parent f2846aa46a
commit 99e768313d
21 changed files with 406 additions and 256 deletions

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml generated
View File

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.12 (gesundheitsassistent)" />
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
@ -8,7 +11,5 @@
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" project-jdk-name="ms-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="ms-17" project-jdk-type="JavaSDK" />
</project>

View File

@ -10,7 +10,7 @@ public class ApplicationContext {
private DataPersistenceService persistenceService;
private StatisticsService statisticsService;
private EvaluationService evaluationService;
private UnrealWebSocketService unrealService;
private AnimationFileService unrealService;
private MqttClientService mqttService;
private BinaryEventService binaryEventService;
private ProcessManagerService processManagerService;
@ -31,7 +31,7 @@ public class ApplicationContext {
this.evaluationService = evaluationService;
}
public void setUnrealService(UnrealWebSocketService unrealService) {
public void setAnimationFileService(AnimationFileService unrealService) {
this.unrealService = unrealService;
}
@ -59,7 +59,7 @@ public class ApplicationContext {
return evaluationService;
}
public UnrealWebSocketService getUnrealService() {
public AnimationFileService getAnimationFileService() {
return unrealService;
}

View File

@ -1,14 +1,11 @@
package vassistent.bootstrap;
import com.formdev.flatlaf.FlatDarkLaf;
import vassistent.controller.DashboardController;
import vassistent.model.AppState;
import vassistent.service.*;
import vassistent.util.ConfigLoader;
import vassistent.util.Logger;
import javax.swing.*;
import java.io.InputStream;
import java.util.Properties;
public class ApplicationInitializer {
@ -26,8 +23,8 @@ public class ApplicationInitializer {
context.setAppState(new AppState());
// ===== Infrastructure Services =====
context.setUnrealService(
new UnrealWebSocketService("ws://localhost:8888/avatar")
context.setAnimationFileService(
new AnimationFileService()
);
context.setMqttService(new MqttClientService(context.getAppState()));
@ -42,7 +39,7 @@ public class ApplicationInitializer {
new EvaluationService(
context.getStatisticsService(),
context.getAppState(),
context.getUnrealService()
context.getAnimationFileService()
)
);

View File

@ -1,25 +1,58 @@
package vassistent.bootstrap;
import vassistent.service.MqttClientService;
import vassistent.service.ProcessManagerService;
import vassistent.util.Logger;
public class ApplicationShutdownManager {
private final ApplicationContext context;
public ApplicationShutdownManager(ApplicationContext context) {
this.context = context;
Runtime.getRuntime().addShutdownHook(
new Thread(this::shutdown)
);
}
public void shutdown() {
if (context.getMqttService() != null) {
context.getMqttService().disconnect();
Logger.info("SHUTDOWN", "Shutdown Sequencing gestartet");
disconnectMqtt();
stopExternalProcesses();
}
if (context.getUnrealService() != null) {
context.getUnrealService().disconnect();
private void disconnectMqtt() {
try {
MqttClientService mqtt = context.getMqttService();
if (mqtt != null) {
mqtt.disconnect();
}
if (context.getProcessManagerService() != null) {
context.getProcessManagerService().shutdown();
Logger.info("SHUTDOWN", "MQTT getrennt");
} catch (Exception e) {
Logger.error("SHUTDOWN", "MQTT Shutdown Fehler", e);
}
}
private void stopExternalProcesses() {
try {
ProcessManagerService pm = context.getProcessManagerService();
if (pm != null) {
pm.shutdown();
}
Logger.info("SHUTDOWN", "Externe Prozesse beendet");
} catch (Exception e) {
Logger.error("SHUWTDOWN", "Process Shutdown Fehler", e);
}
}
}

View File

@ -5,8 +5,11 @@ import vassistent.bootstrap.ApplicationShutdownManager;
import vassistent.model.AppState;
import vassistent.ui.AppWindow;
import vassistent.ui.DashboardView;
import vassistent.ui.PixelStreamingView;
import vassistent.util.Logger;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
@ -28,6 +31,7 @@ public class AppWindowController {
window = new AppWindow();
DashboardView dashboardView = window.getDashboardView();
PixelStreamingView pixelStreamingView = window.getStreamingView();
DashboardController dashboardController =
new DashboardController(
@ -36,8 +40,16 @@ public class AppWindowController {
context.getAppState()
);
window.getRefreshDashboardButton()
.addActionListener(e -> dashboardController.loadChartData());
StreamingController previewController = new StreamingController(pixelStreamingView);
dashboardView.getReloadPixelStreamingViewButton()
.addActionListener(e ->
previewController.reloadStream("http://141.75.215.233")
);
dashboardView.getOpenFullscreenButton()
.addActionListener(e ->
window.getStreamingView().requestFocus());
window.addWindowListener(new WindowAdapter() {
@Override
@ -66,11 +78,13 @@ public class AppWindowController {
AppState state = context.getAppState();
state.addListener(appState -> {
state.addListener(this::onStateChanged);
/*Logger.debug("Controller",
"AppState Update erhalten: " +
appState.getProblemLevel());*/
Logger.info("Controller",
"AppState Observer registriert");
}
private void onStateChanged(AppState appState) {
if (window == null) {
Logger.warn("Controller",
@ -78,6 +92,8 @@ public class AppWindowController {
return;
}
SwingUtilities.invokeLater(() -> {
window.updateProblemLevel(
appState.getProblemLevel().name()
);
@ -87,11 +103,8 @@ public class AppWindowController {
);
Logger.debug("Controller",
"ProblemLevel UI aktualisiert → " +
appState.getProblemLevel());
"ProblemLevel UI aktualisiert → "
+ appState.getProblemLevel());
});
Logger.info("Controller",
"AppState Observer registriert");
}
}

View File

@ -5,6 +5,7 @@ import vassistent.model.RatioPoint;
import vassistent.service.StatisticsService;
import vassistent.ui.DashboardView;
import javax.swing.*;
import java.util.List;
public class DashboardController {
@ -21,14 +22,23 @@ public class DashboardController {
this.statisticsService = statisticsService;
this.dashboardView = dashboardView;
appState.addListener(state -> {
if (state.getDataVersion() != lastDataVersion) {
lastDataVersion = state.getDataVersion();
List<RatioPoint> points = statisticsService.getLastNAverages(20);
dashboardView.updateChart(points);
appState.addListener(this::onStateChanged);
}
private void onStateChanged(AppState state) {
List<RatioPoint> points =
statisticsService.getLastNAverages(20);
if (points.isEmpty())
return;
double ratio = points.get(points.size() - 1).getRatio();
SwingUtilities.invokeLater(() -> {
dashboardView.updateChart(points);
dashboardView.updateProblemLevel(ratio);
});
}

View File

@ -27,6 +27,7 @@ public class AppState {
public void setProblemLevel(ProblemLevel problemLevel) {
this.problemLevel = problemLevel;
dataVersion++;
notifyListeners();
}
@ -40,13 +41,4 @@ public class AppState {
notifyListeners();
}
}
public long getDataVersion() {
return dataVersion;
}
public void incrementDataVersion() {
dataVersion++;
notifyListeners();
}
}

View File

@ -0,0 +1,50 @@
package vassistent.service;
import vassistent.model.ProblemLevel;
import vassistent.util.Logger;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.atomic.AtomicBoolean;
import jakarta.websocket.*;
public class AnimationFileService {
private static final String PATH = "C:\\Privat\\Dokumente\\Niklas_Aumueller\\TH\\MSY\\Semester_2\\animation.json";
public void wirteAnimationState(ProblemLevel level) {
String animation = mapLevelToAnimation(level);
File file = new File(PATH);
try {
String json = """
{
"animation": "%s"
}
""".formatted(animation);
try (FileWriter writer = new FileWriter(file, false)) {
writer.write(json);
}
Logger.info("ANIMATION FILE", "Animation json geschrieben");
} catch (IOException e) {
Logger.error("ANIMATION FILE", "Fehler beim Schreiben der Animation Datei", e);
}
}
private String mapLevelToAnimation(ProblemLevel level) {
return switch (level) {
case NONE -> "no";
case WARNING -> "warning";
case HIGH -> "high";
case DISASTER -> "disaster";
};
}
}

View File

@ -7,28 +7,26 @@ import vassistent.model.ProblemLevel;
public class EvaluationService {
private final StatisticsService statisticsService;
private final AppState appState;
private final UnrealWebSocketService unrealService;
private final AnimationFileService animationFileService;
public EvaluationService(
StatisticsService statisticsService,
AppState appState,
UnrealWebSocketService unrealService
AnimationFileService animationFileService
) {
this.statisticsService = statisticsService;
this.appState = appState;
this.unrealService = unrealService;
this.animationFileService = animationFileService;
}
public void evaluate() {
double ratio = statisticsService.getRatio(10);
double ratio = statisticsService.getRatio(20);
ProblemLevel level = calculateLevel(ratio);
appState.setProblemLevel(level);
unrealService.speak(level.name());
appState.incrementDataVersion();
animationFileService.wirteAnimationState(level);
}
private ProblemLevel calculateLevel(Double ratio) {

View File

@ -23,7 +23,6 @@ public class MqttClientService implements MqttCallback {
public MqttClientService(AppState appState) {
this.appState = appState;
try {
client = new MqttClient(
BROKER_URL,
@ -107,6 +106,7 @@ public class MqttClientService implements MqttCallback {
Consumer<String> listener = topicListeners.get(topic);
if (listener != null) {
listener.accept(payload);
Logger.debug("MQTT", "Payload accepted");
} else {
Logger.warn(
"MQTT",

View File

@ -1,5 +0,0 @@
package vassistent.service;
public class PixelStreamingService {
}

View File

@ -12,6 +12,7 @@ public class ProcessManagerService {
private Process pythonProcess;
private Process unrealProcess;
private Process unrealSignallingProcess;
public ProcessManagerService(Properties config) {
this.config = config;
@ -54,34 +55,92 @@ public class ProcessManagerService {
try {
String exe = config.getProperty("unreal.executable");
startSignallingServer();
startUnrealEngine();
} catch (IOException e) {
Logger.error("PROCESS", "Unreal Start fehlgeschlagen", e);
}
}
private void startSignallingServer() throws IOException {
String script =
config.getProperty("unreal.signalling_server.script");
if (script == null) return;
ProcessBuilder pb = new ProcessBuilder(
"cmd",
"/c",
script);
pb.redirectErrorStream(true);
unrealSignallingProcess = pb.start();
Logger.info("PROCESS",
"Unreal Signalling Server gestartet" + pb.command());
}
private void startUnrealEngine() throws IOException {
String exe =
config.getProperty("unreal.executable");
ProcessBuilder pb = new ProcessBuilder(
exe,
"-RenderOffScreen",
"-NoSound",
"-PixelStreamingSignallingURL=ws://127.0.0.1:8888"
"-PixelStreamingURL=ws://127.0.0.1:8888",
"-RenderOffscreen",
"-NoSound"
);
pb.directory(new File(exe).getParentFile());
pb.redirectErrorStream(true);
unrealProcess = pb.start();
Logger.info("PROCESS", "Unreal Engine Avatar");
} catch (IOException e) {
Logger.error("PROCESS", "Unreal Engine Start fehlgeschlagen", e);
}
Logger.info("PROCESS",
"Unreal Engine gestartet" + pb.command());
}
public void shutdown() {
if (pythonProcess != null)
pythonProcess.destroyForcibly();
Logger.info("PROCESS", "Shutdown externe Prozesse gestartet");
if (unrealProcess != null)
unrealProcess.destroyForcibly();
terminateProcess(pythonProcess);
terminateProcess(unrealProcess);
terminateProcess(unrealSignallingProcess);
Logger.info("PROCESS", "Externe Prozesse beendet");
}
private void terminateProcess(Process process) {
if (process == null)
return;
try {
long pid = process.pid();
ProcessBuilder pb = new ProcessBuilder(
"taskkill",
"/PID",
String.valueOf(pid),
"/T",
"/F"
);
pb.start().waitFor();
Logger.info("PROCESS",
"Process Tree beendet → PID " + pid);
} catch (Exception e) {
Logger.error("PROCESS",
"Fehler beim Prozess Kill", e);
}
}
}

View File

@ -1,13 +0,0 @@
package vassistent.service;
import vassistent.model.AppState;
public class StateService {
private static final AppState STATE = new AppState();
private StateService() {}
public static AppState getState() {
return STATE;
}
}

View File

@ -1,95 +0,0 @@
package vassistent.service;
import vassistent.util.Logger;
import java.net.URI;
import java.util.concurrent.atomic.AtomicBoolean;
import jakarta.websocket.*;
public class UnrealWebSocketService {
private Session session;
private final URI serverUri;
private final AtomicBoolean connected = new AtomicBoolean(false);
public UnrealWebSocketService(String serverUrl) {
this.serverUri = URI.create(serverUrl);
//connect();
}
private void connect() {
try {
WebSocketContainer container =
ContainerProvider.getWebSocketContainer();
Logger.info("UNREAL", "Verbinde zu " + serverUri);
container.connectToServer(this, serverUri);
} catch (Exception e) {
Logger.error("UNREAL", "WebSocket-Verbindung fehlgeschlagen", e);
}
}
public boolean isConnected() {
return connected.get();
}
public void disconnect() {
try {
if (session != null && session.isOpen()) {
session.close();
Logger.info("UNREAL", "WebSocket-Verbindung geschlossen");
}
} catch (Exception e) {
Logger.error("UNREAL", "Fehler beim Schließen der Verbindung", e);
}
}
@OnOpen
public void onOpen(Session session) {
this.session = session;
connected.set(true);
Logger.info("UNREAL", "WebSocket verbunden");
}
@OnClose
public void onClose(Session session, CloseReason reason) {
connected.set(false);
Logger.warn("UNREAL", "WebSocket geschlossen: " + reason.getReasonPhrase());
}
@OnError
public void onError(Session session, Throwable throwable) {
connected.set(false);
Logger.error("UNREAL", "WebSocket-Fehler", throwable);
}
@OnMessage
public void onMessage(String message) {
Logger.debug("UNREAL", "Nachricht empfangen: " + message);
}
public void speak(String text) {
if (!connected.get()) {
//Logger.warn("UNREAL", "Nicht verbunden! Text wird nicht gesendet!");
return;
}
String json = buildSpeakMessage(text);
session.getAsyncRemote().sendText(json);
Logger.info("UNREAL", "Sende Speak-Command: " + text);
}
public String buildSpeakMessage(String text) {
return "{"
+ "\"type\":\"speak\","
+ "\"text\":\"" + escape(text) + "\""
+ "}";
}
public String escape(String text) {
return text.replace("\"", "\\\"");
}
}

View File

@ -10,15 +10,11 @@ public class AppWindow extends JFrame {
private PixelStreamingView streamingView;
private DashboardView dashboardView;
private JTabbedPane tabs;
private JLabel mqttStatusLabel;
private JLabel websocketStatusLabel;
private JLabel problemLevelLabel;
private JButton refreshDashboardButton;
private JButton reloadStreamButton;
private JButton fullscreenButton;
public AppWindow() {
setTitle("Virtueller Gesundheitsassistent");
@ -28,41 +24,27 @@ public class AppWindow extends JFrame {
setLayout(new BorderLayout());
add(createToolbar(), BorderLayout.NORTH);
add(createTabPane(), BorderLayout.CENTER);
streamingView = new PixelStreamingView(
"http://localhost:80",
false,
false
);
dashboardView = new DashboardView();
tabs = createTabPane();
add(tabs, BorderLayout.CENTER);
add(createStatusBar(), BorderLayout.SOUTH);
}
// ---------------- Toolbar ----------------
private JPanel createToolbar() {
JPanel toolbar = new JPanel(new FlowLayout(FlowLayout.LEFT));
refreshDashboardButton = new JButton("Dashboard Refresh");
reloadStreamButton = new JButton("Stream Reload");
fullscreenButton = new JButton("Fullscreen Stream");
toolbar.add(refreshDashboardButton);
toolbar.add(reloadStreamButton);
toolbar.add(fullscreenButton);
return toolbar;
}
// ---------------- Tabs ----------------
private JTabbedPane createTabPane() {
JTabbedPane tabs = new JTabbedPane();
streamingView = new PixelStreamingView(
"http://141.75.215.233",
false,
false
);
dashboardView = new DashboardView();
JPanel streamingPanel = new JPanel(new BorderLayout());
streamingPanel.add(streamingView, BorderLayout.CENTER);
tabs.addTab("Avatar Streaming", streamingView);
tabs.addTab("Dashboard", dashboardView);
@ -77,13 +59,10 @@ public class AppWindow extends JFrame {
JPanel statusBar = new JPanel(new FlowLayout(FlowLayout.LEFT));
mqttStatusLabel = new JLabel("MQTT: Disconnected");
websocketStatusLabel = new JLabel();
problemLevelLabel = new JLabel("Problem: NONE");
statusBar.add(mqttStatusLabel);
statusBar.add(new JLabel(" | "));
statusBar.add(websocketStatusLabel);
statusBar.add(new JLabel(" | "));
statusBar.add(problemLevelLabel);
return statusBar;
@ -94,11 +73,6 @@ public class AppWindow extends JFrame {
(connected ? "Connected" : "Disconnected"));
}
public void updateWebsocketStatus(boolean connected) {
websocketStatusLabel.setText("WebSocket: " +
(connected ? "Connected" : "Disconnected"));
}
public void updateProblemLevel(String level) {
problemLevelLabel.setText("Problem: " + level);
}
@ -111,15 +85,7 @@ public class AppWindow extends JFrame {
return streamingView;
}
public JButton getRefreshDashboardButton() {
return refreshDashboardButton;
}
public JButton getReloadStreamButton() {
return reloadStreamButton;
}
public JButton getFullscreenButton() {
return fullscreenButton;
public JTabbedPane getTabs() {
return tabs;
}
}

View File

@ -7,6 +7,7 @@ import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import vassistent.model.ProblemLevel;
import vassistent.model.RatioPoint;
import javax.swing.*;
@ -20,14 +21,23 @@ import java.util.List;
public class DashboardView extends JPanel {
private TimeSeries series;
private ProblemLevelBar levelBar;
private JButton reloadPixelStreamingViewButton;
private JButton openFullscreenButton;
public DashboardView() {
setLayout(new BorderLayout());
// ---------- TOP: Problem Level ----------
levelBar = new ProblemLevelBar();
add(levelBar, BorderLayout.NORTH);
// ---------- CENTER: Chart ----------
series = new TimeSeries("Ratio");
TimeSeriesCollection dataset =
new TimeSeriesCollection(series);
TimeSeriesCollection dataset = new TimeSeriesCollection(series);
JFreeChart chart = ChartFactory.createTimeSeriesChart(
"Ratio Verlauf",
@ -36,9 +46,27 @@ public class DashboardView extends JPanel {
dataset
);
ChartPanel chartPanel = new ChartPanel(chart);
add(new ChartPanel(chart), BorderLayout.CENTER);
add(chartPanel, BorderLayout.CENTER);
// ---------- SOUTH: Preview + Buttons ----------
add(createBottomPanel(), BorderLayout.SOUTH);
}
private JPanel createBottomPanel() {
JPanel panel = new JPanel(new BorderLayout());
JPanel buttonPanel = new JPanel(new FlowLayout());
reloadPixelStreamingViewButton = new JButton("Reload Preview");
openFullscreenButton = new JButton("Open Fullscreen");
buttonPanel.add(reloadPixelStreamingViewButton);
buttonPanel.add(openFullscreenButton);
panel.add(buttonPanel, BorderLayout.SOUTH);
return panel;
}
public void updateChart(List<RatioPoint> points) {
@ -59,5 +87,15 @@ public class DashboardView extends JPanel {
}
}
public void updateProblemLevel(double ratio) {
levelBar.setRatio(ratio);
}
public JButton getReloadPixelStreamingViewButton() {
return reloadPixelStreamingViewButton;
}
public JButton getOpenFullscreenButton() {
return openFullscreenButton;
}
}

View File

@ -0,0 +1,89 @@
package vassistent.ui;
import vassistent.model.ProblemLevel;
import javax.swing.*;
import java.awt.*;
public class ProblemLevelBar extends JPanel {
private double ratio = 0.0;
private ProblemLevel level = ProblemLevel.NONE;
public ProblemLevelBar() {
setPreferredSize(new Dimension(100, 50));
}
public void setRatio(double ratio) {
this.ratio = Math.max(0.0, Math.min(1.0, ratio));
this.level = calculateLevel(this.ratio);
repaint();
}
private ProblemLevel calculateLevel(Double ratio) {
if (ratio >= 0.9) {
return ProblemLevel.DISASTER;
} else if (ratio >= 0.8) {
return ProblemLevel.HIGH;
} else if (ratio >= 0.5) {
return ProblemLevel.WARNING;
} else {
return ProblemLevel.NONE;
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// --- Hintergrund ---
g2.setColor(Color.LIGHT_GRAY);
g2.fillRoundRect(0, 0, width, height, 20, 20);
// --- Gefüllter Bereich ---
int filledWidth = (int) (width * ratio);
Color baseColor = getColorForLevel(level);
Color darkerColor = baseColor.darker();
GradientPaint gradient = new GradientPaint(
0, 0, darkerColor,
filledWidth, 0, baseColor
);
g2.setPaint(gradient);
g2.fillRoundRect(0, 0, filledWidth, height, 20, 20);
// --- Text ---
String text = level.name() + " (" + (int)(ratio * 100) + "%)";
FontMetrics fm = g2.getFontMetrics();
int textWidth = fm.stringWidth(text);
g2.setColor(Color.BLACK);
g2.drawString(
text,
(width - textWidth) / 2,
(height + fm.getAscent()) / 2 - 3
);
}
private Color getColorForLevel(ProblemLevel level) {
switch (level) {
case DISASTER:
return new Color(200, 0, 0);
case HIGH:
return new Color(255, 140, 0);
case WARNING:
return new Color(255, 215, 0);
default:
return new Color(0, 170, 0);
}
}
}

View File

@ -2,16 +2,16 @@
app.mode=test
# ===== PYTHON =====
python.path="C:\\Program Files\\PyManager\\python.exe"
python.path=C:\\Program Files\\PyManager\\python.exe
# ===== MQTT CLIENT =====
mqtt.topic=PREDICTION
# ===== MQTT SIMULATOR =====
mqtt_sim.enabled=false
mqtt_sim.enabled=true
mqtt_sim.script=src/main/resources/scripts/mqtt_simulator.py
# ===== UNREAL ENGINE =====
unreal.enabled=false
unreal.executable=external/unreal/avatar.exe
unreal.signalling_server.script=external/unreal/start.bat
unreal.enabled=true
unreal.executable=C:\\Privat\\Dokumente\\Niklas_Aumueller\\TH\\MSY\\Semester_2\\Projektarbeit\\Windows\\Prototyp1.exe
unreal.signalling_server.script=C:\\Privat\\Dokumente\\Niklas_Aumueller\\TH\\MSY\\Semester_2\\Projektarbeit\\Windows\\Prototyp1\\Samples\\PixelStreaming\\WebServers\\SignallingWebServer\\platform_scripts\\cmd\\start_with_stun.bat

View File

@ -1,3 +1,5 @@
import json
import paho.mqtt.client as mqtt
import sys
import random
@ -44,17 +46,26 @@ def main():
try:
logging.info(f"Verbinde mit Broker {BROKER}:{PORT}")
client.connect(BROKER, PORT, 60)
client.loop_start()
logging.info("Starte kontinuierliches Senden...")
while True:
message = random.randint(0, 1)
current_id = 1
client.publish(TOPIC, message, qos=QOS)
logging.info(f"Gesendet an '{TOPIC}': {message}")
while True:
payload = {
"valid": True,
"_id": current_id,
"prediction": random.randint(0, 1)
}
json_payload = json.dumps(payload)
client.publish(TOPIC, json_payload, qos=QOS)
logging.info(f"Gesendet an '{TOPIC}': {json_payload}")
current_id += 1
time.sleep(INTERVAL_SECONDS)

View File

@ -12,14 +12,14 @@ class EvaluationServiceTest {
private StatisticsService statisticsService;
private AppState appState;
private UnrealWebSocketService unrealService;
private AnimationFileService unrealService;
private EvaluationService evaluationService;
@BeforeEach
void setUp() {
statisticsService = mock(StatisticsService.class);
appState = new AppState();
unrealService = mock(UnrealWebSocketService.class);
unrealService = mock(AnimationFileService.class);
evaluationService = new EvaluationService(statisticsService, appState, unrealService);
}