diff --git a/.gitignore b/.gitignore index c3a54ec..a70ceec 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ target/ *.iws *.iml *.ipr +src/main/resources/scripts/.venv/ lib/ logs/ data/ diff --git a/out/artifacts/Virtueller_Gesundheitsassistent_jar/Virtueller_Gesundheitsassistent.jar b/out/artifacts/Virtueller_Gesundheitsassistent_jar/Virtueller_Gesundheitsassistent.jar index 117a868..18b2bce 100644 Binary files a/out/artifacts/Virtueller_Gesundheitsassistent_jar/Virtueller_Gesundheitsassistent.jar and b/out/artifacts/Virtueller_Gesundheitsassistent_jar/Virtueller_Gesundheitsassistent.jar differ diff --git a/src/main/java/vassistent/controller/DashboardController.java b/src/main/java/vassistent/controller/DashboardController.java index a060bf6..04da970 100644 --- a/src/main/java/vassistent/controller/DashboardController.java +++ b/src/main/java/vassistent/controller/DashboardController.java @@ -4,6 +4,7 @@ import vassistent.model.AppState; import vassistent.model.RatioPoint; import vassistent.service.StatisticsService; import vassistent.ui.DashboardView; +import vassistent.util.Logger; import javax.swing.*; import java.util.List; @@ -28,17 +29,19 @@ public class DashboardController { private void onStateChanged(AppState state) { List points = - statisticsService.getLastNAverages(20); - - if (points.isEmpty()) - return; - - double ratio = points.get(points.size() - 1).getRatio(); + statisticsService.getLastNAverages(120); SwingUtilities.invokeLater(() -> { + Logger.info("STATISTICS", + "Entries loaded: " + points.size()); + dashboardView.updateChart(points); - dashboardView.updateProblemLevel(ratio); + + if (!points.isEmpty()) { + double ratio = points.get(points.size() - 1).getRatio(); + dashboardView.updateProblemLevel(ratio); + } }); } diff --git a/src/main/java/vassistent/model/AppState.java b/src/main/java/vassistent/model/AppState.java index 98fdde7..a6d8f1d 100644 --- a/src/main/java/vassistent/model/AppState.java +++ b/src/main/java/vassistent/model/AppState.java @@ -18,7 +18,7 @@ public class AppState { } private void notifyListeners() { - listeners.forEach(l -> l.accept(this)); + new ArrayList<>(listeners).forEach(l -> l.accept(this)); } public ProblemLevel getProblemLevel() { diff --git a/src/main/java/vassistent/service/BinaryEventService.java b/src/main/java/vassistent/service/BinaryEventService.java index d5932ce..0b630a9 100644 --- a/src/main/java/vassistent/service/BinaryEventService.java +++ b/src/main/java/vassistent/service/BinaryEventService.java @@ -38,7 +38,7 @@ public class BinaryEventService { if (lastId != null && lastId == id) { Logger.warn("EVENT", "Payload ID bereits verarbeitet: " + id); - return; + //return; } lastId = id; diff --git a/src/main/java/vassistent/service/StatisticsService.java b/src/main/java/vassistent/service/StatisticsService.java index 7b604b1..62b3a31 100644 --- a/src/main/java/vassistent/service/StatisticsService.java +++ b/src/main/java/vassistent/service/StatisticsService.java @@ -41,29 +41,37 @@ public class StatisticsService { return 0.0; } - public List getLastNAverages(int lastN) { + public List getLastNAverages(int windowSize) { - List entries = persistenceService.getLastEntries(30); + List entries = persistenceService.getLastEntries(windowSize + 1); List result = new ArrayList<>(); if (entries.isEmpty()) return result; - for (int i = 10; i < entries.size(); i++) { - double sum = 0; + for (int i = 0; i < entries.size(); i++) { + int start = Math.max(0, i - windowSize); - for (int j = i - 10; j < i; j++) { + double sum = 0; + int count = 0; + + for (int j = start; j < i; j++) { sum += entries.get(j).getValue(); + count++; } - double avg = sum / 10.0; + double avg = count == 0 ? 0 : sum / count; - LocalDateTime timestamp = entries.get(i).getTimestamp(); - - result.add(new RatioPoint(timestamp, avg)); + result.add(new RatioPoint( + entries.get(i).getTimestamp(), + avg + )); } + Logger.info("STATISTICS", + "Computed averages: " + result.size()); + return result; } } diff --git a/src/main/java/vassistent/ui/DashboardView.java b/src/main/java/vassistent/ui/DashboardView.java index e84bc92..2b07919 100644 --- a/src/main/java/vassistent/ui/DashboardView.java +++ b/src/main/java/vassistent/ui/DashboardView.java @@ -3,10 +3,13 @@ package vassistent.ui; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.DateAxis; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.NumberTickUnit; import org.jfree.chart.plot.ValueMarker; import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.chart.ui.Layer; import org.jfree.chart.ui.RectangleAnchor; import org.jfree.chart.ui.TextAnchor; import org.jfree.data.category.DefaultCategoryDataset; @@ -75,6 +78,24 @@ public class DashboardView extends JPanel { XYPlot plot = chart.getXYPlot(); + long tenMinutes = 10 * 60 * 1000L; + + DateAxis domainAxis = (DateAxis) plot.getDomainAxis(); + + domainAxis.setFixedAutoRange(tenMinutes); + domainAxis.setAutoRange(true); + + XYLineAndShapeRenderer renderer = + (XYLineAndShapeRenderer) plot.getRenderer(); + + renderer.setDefaultShapesVisible(false); + renderer.setSeriesStroke(0, + new BasicStroke( + 2.5f, + BasicStroke.CAP_ROUND, + BasicStroke.JOIN_ROUND + )); + // Threshold Lines addThresholdLine(plot, 0.5, "Warning"); addThresholdLine(plot, 0.8, "High"); @@ -85,6 +106,7 @@ public class DashboardView extends JPanel { rangeAxis.setTickUnit(new NumberTickUnit(0.1)); chart.setAntiAlias(true); + chart.setTextAntiAlias(true); chart.getPlot().setBackgroundPaint(new Color(245,245,245)); chart.getPlot().setOutlineVisible(false); @@ -121,6 +143,9 @@ public class DashboardView extends JPanel { } public void updateChart(List points) { + if (points == null || points.isEmpty()) + return; + series.clear(); for (RatioPoint point : points) { @@ -154,13 +179,25 @@ public class DashboardView extends JPanel { ValueMarker marker = new ValueMarker(value); - marker.setPaint(Color.RED); - marker.setStroke(new BasicStroke(1.5f)); + marker.setPaint(new Color(150,150,150,150)); + + float[] dash = {6.0f, 6.0f}; + marker.setStroke(new BasicStroke( + 1f, + BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, + 10.0f, + dash, + 0.0f + )); + marker.setLabel(label); marker.setLabelFont(new Font("Segoe UI", Font.PLAIN, 11)); - marker.setLabelAnchor(RectangleAnchor.LEFT); - marker.setLabelTextAnchor(TextAnchor.BOTTOM_LEFT); + marker.setLabelPaint(new Color(160,160,160)); - plot.addRangeMarker(marker); + marker.setLabelAnchor(RectangleAnchor.RIGHT); + marker.setLabelTextAnchor(TextAnchor.TOP_RIGHT); + + plot.addRangeMarker(marker, Layer.BACKGROUND); } } diff --git a/src/main/resources/scripts/mqtt_simulator.py b/src/main/resources/scripts/mqtt_simulator.py index ae6caa1..99c39c0 100644 --- a/src/main/resources/scripts/mqtt_simulator.py +++ b/src/main/resources/scripts/mqtt_simulator.py @@ -7,13 +7,13 @@ import time import logging # ===== KONFIGURATION ===== -BROKER = "127.0.0.1" +BROKER = "141.75.223.13" PORT = 1883 TOPIC = "PREDICTION" USERNAME = None PASSWORD = None QOS = 0 -INTERVAL_SECONDS = 10 +INTERVAL_SECONDS = 5 # ========================== # Logging konfigurieren (Console + Datei)